Compare commits
108 Commits
@0x/contra
...
feat/Proto
Author | SHA1 | Date | |
---|---|---|---|
|
40b6d9a56a | ||
|
faac36d8d8 | ||
|
291ba8f28e | ||
|
79565bd2f4 | ||
|
4d55bc11c9 | ||
|
81bd825369 | ||
|
adf35091c0 | ||
|
d8311b1de1 | ||
|
c874beab91 | ||
|
7b8c1a7e1d | ||
|
1b6b238d79 | ||
|
a8264822d2 | ||
|
7e0ed41759 | ||
|
19e7dd6af1 | ||
|
43aeec4711 | ||
|
06763ac275 | ||
|
359b36a6c7 | ||
|
7503ef37ba | ||
|
a5bee1f363 | ||
|
54da1e733c | ||
|
ce82d3529c | ||
|
32b0743517 | ||
|
9d51c0f7ce | ||
|
830a6474c1 | ||
|
5d8e1da37c | ||
|
34acdd64fc | ||
|
e90ffcf1d7 | ||
|
6f7ef9c54f | ||
|
1c51f5962b | ||
|
a942e03e94 | ||
|
cc387ae176 | ||
|
8bfb58eba9 | ||
|
1f76e3c949 | ||
|
7af372f56b | ||
|
2a2bb53d9c | ||
|
0f2078e70f | ||
|
d3396fff3c | ||
|
68bc3979dd | ||
|
7b98c436a5 | ||
|
9bda78c57b | ||
|
6c0d1d8a37 | ||
|
777f83c702 | ||
|
01f4e0eb48 | ||
|
95454fdaff | ||
|
a47e7ee105 | ||
|
330b8e96e5 | ||
|
0a529e7f96 | ||
|
294a4d2d71 | ||
|
160d6a0ff2 | ||
|
3a005254dd | ||
|
014acef6f6 | ||
|
52ca453a63 | ||
|
e3d90fb7f1 | ||
|
c04a326c30 | ||
|
19aebbdf02 | ||
|
679f1fd625 | ||
|
cb81fa322e | ||
|
85daeaca54 | ||
|
a7c0c761ce | ||
|
300a64947c | ||
|
f395be9269 | ||
|
0558203407 | ||
|
895754750f | ||
|
f856f449ad | ||
|
aac291ddcf | ||
|
87b97ff4b5 | ||
|
a933ea502f | ||
|
91238d7bfa | ||
|
bc6253059e | ||
|
3ef9d50742 | ||
|
498698471f | ||
|
7223ea0c0a | ||
|
d0bc0d7936 | ||
|
2bbdf29df8 | ||
|
353dffa6c3 | ||
|
1cdc5e0679 | ||
|
26edf14859 | ||
|
8857ef6b4c | ||
|
d6fbb43c10 | ||
|
4929c60565 | ||
|
aca9338acb | ||
|
d775e780ad | ||
|
b197bf734d | ||
|
95aa9d0150 | ||
|
edb3d11e59 | ||
|
9f047f9fd5 | ||
|
dea5cb8ac9 | ||
|
300ff1d7e8 | ||
|
ccd7aa0c5e | ||
|
f2140a153e | ||
|
dd02415f8e | ||
|
692eee0cf2 | ||
|
1d96d7fd8e | ||
|
706ef6d2ec | ||
|
504924a685 | ||
|
a7801c7e77 | ||
|
8389ef31d8 | ||
|
7967ccfb9d | ||
|
da279052b1 | ||
|
35c0cafd6b | ||
|
bd0d672012 | ||
|
27ae6aabd1 | ||
|
f46b878637 | ||
|
6334f5bd84 | ||
|
d1a93737ce | ||
|
29c77059a0 | ||
|
7d5e4ed685 | ||
|
6ac7dd006c |
@@ -1,10 +1,5 @@
|
||||
version: 2.1
|
||||
|
||||
parameters:
|
||||
cache_version:
|
||||
type: string
|
||||
default: v5
|
||||
|
||||
jobs:
|
||||
build:
|
||||
resource_class: xlarge
|
||||
@@ -12,16 +7,10 @@ jobs:
|
||||
- image: node:16
|
||||
environment:
|
||||
NODE_OPTIONS: '--max-old-space-size=16384'
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: git submodule update --init --recursive
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-feat/NerveMixinArbitrum
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- run:
|
||||
name: install-yarn
|
||||
command: npm install --force --global yarn@1.22.0
|
||||
@@ -29,155 +18,65 @@ jobs:
|
||||
name: yarn
|
||||
command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install
|
||||
- setup_remote_docker
|
||||
- run: yarn build:ci
|
||||
- run: yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci
|
||||
- save_cache:
|
||||
key: cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/project/node_modules
|
||||
- ~/.cache/yarn
|
||||
- save_cache:
|
||||
key: lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
paths:
|
||||
- ~/project/contracts/erc20/generated-artifacts/
|
||||
- ~/project/contracts/erc20/generated-wrappers/
|
||||
- ~/project/contracts/erc20/lib/
|
||||
- ~/project/contracts/erc20/node_modules
|
||||
- ~/project/contracts/erc20/test/generated-artifacts/
|
||||
- ~/project/contracts/erc20/test/generated-wrappers/
|
||||
- ~/project/contracts/test-utils/lib/
|
||||
- ~/project/contracts/test-utils/node_modules
|
||||
- ~/project/contracts/treasury/generated-artifacts/
|
||||
- ~/project/contracts/treasury/generated-wrappers/
|
||||
- ~/project/contracts/treasury/lib/
|
||||
- ~/project/contracts/treasury/node_modules
|
||||
- ~/project/contracts/treasury/test/generated-artifacts/
|
||||
- ~/project/contracts/treasury/test/generated-wrappers/
|
||||
- ~/project/contracts/utils/generated-artifacts/
|
||||
- ~/project/contracts/utils/generated-wrappers/
|
||||
- ~/project/contracts/utils/lib/
|
||||
- ~/project/contracts/utils/node_modules
|
||||
- ~/project/contracts/utils/test/generated-artifacts/
|
||||
- ~/project/contracts/utils/test/generated-wrappers/
|
||||
- ~/project/contracts/zero-ex/generated-artifacts/
|
||||
- ~/project/contracts/zero-ex/generated-wrappers/
|
||||
- ~/project/contracts/zero-ex/lib/
|
||||
- ~/project/contracts/zero-ex/node_modules
|
||||
- ~/project/contracts/zero-ex/test/generated-artifacts/
|
||||
- ~/project/contracts/zero-ex/test/generated-wrappers/
|
||||
- ~/project/packages/asset-swapper/node_modules
|
||||
- ~/project/packages/contract-addresses/lib/
|
||||
- ~/project/packages/contract-addresses/node_modules
|
||||
- ~/project/packages/contract-artifacts/lib/
|
||||
- ~/project/packages/contract-artifacts/node_modules
|
||||
- ~/project/packages/contract-wrappers/lib/
|
||||
- ~/project/packages/contract-wrappers/node_modules
|
||||
- ~/project/packages/protocol-utils/lib/
|
||||
- ~/project/packages/protocol-utils/node_modules
|
||||
- ~/repo
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/abi-gen/test-cli/output
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/contract-wrappers/generated_docs
|
||||
test-exchange-ganache:
|
||||
resource_class: xlarge
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-exchange -m --serial -c test:circleci
|
||||
test-integrations-ganache:
|
||||
resource_class: xlarge
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-integrations -m --serial -c test:circleci
|
||||
test-contracts-staking-ganache:
|
||||
resource_class: xlarge
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-staking -m --serial -c test:circleci
|
||||
test-contracts-extra-ganache:
|
||||
resource_class: xlarge
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-exchange-forwarder -p @0x/contracts-coordinator -m --serial -c test:circleci
|
||||
test-contracts-rest-ganache:
|
||||
resource_class: xlarge
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
git diff --name-only development >> changed.txt
|
||||
if ! grep -q \.sol changed.txt; then
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- run: |
|
||||
yarn wsrun \
|
||||
-p @0x/contracts-multisig \
|
||||
-p @0x/contracts-utils \
|
||||
-p @0x/contracts-exchange-libs \
|
||||
-p @0x/contracts-erc20 \
|
||||
-p @0x/contracts-erc721 \
|
||||
-p @0x/contracts-erc1155 \
|
||||
-p @0x/contracts-asset-proxy \
|
||||
-p @0x/contracts-broker \
|
||||
-p @0x/contracts-zero-ex \
|
||||
-m --serial -c test:circleci
|
||||
test-foundry:
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: ghcr.io/foundry-rs/foundry:latest
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
git diff --name-only development >> changed.txt
|
||||
cat changed.txt
|
||||
if ! grep -q \.sol changed.txt; then
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- run: git submodule update --init --recursive
|
||||
- run:
|
||||
command: forge test
|
||||
working_directory: ~/project/contracts/zero-ex
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-multisig -p @0x/contracts-utils -p @0x/contracts-exchange-libs -p @0x/contracts-erc20 -p @0x/contracts-erc721 -p @0x/contracts-erc1155 -p @0x/contracts-asset-proxy -p @0x/contracts-broker -p @0x/contracts-zero-ex -m --serial -c test:circleci
|
||||
test-publish:
|
||||
resource_class: large
|
||||
environment:
|
||||
@@ -185,20 +84,11 @@ jobs:
|
||||
docker:
|
||||
- image: node:16
|
||||
- image: 0xorg/verdaccio
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
git diff --name-only development >> changed.txt
|
||||
cat changed.txt
|
||||
if ! grep -q packages/ changed.txt; then
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: yarn test:publish:circleci
|
||||
no_output_timeout: 1800
|
||||
@@ -207,88 +97,71 @@ jobs:
|
||||
test-doc-generation:
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: yarn test:generate_docs:circleci
|
||||
no_output_timeout: 1200
|
||||
test-rest:
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
environment:
|
||||
RUST_ROUTER: 'true'
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun -p @0x/contracts-test-utils -m --serial -c test:circleci
|
||||
- run: yarn wsrun -p @0x/contract-addresses -m --serial -c test:circleci
|
||||
- run: yarn wsrun -p @0x/contract-artifacts -m --serial -c test:circleci
|
||||
- run: yarn wsrun -p @0x/contract-wrappers-test -m --serial -c test:circleci
|
||||
- run: yarn wsrun -p @0x/order-utils -m --serial -c test:circleci
|
||||
- run: yarn wsrun -p @0x/asset-swapper -m --serial -c test:circleci
|
||||
- save_cache:
|
||||
key: coverage-contract-wrappers-test-{{ checksum "yarn.lock" }}
|
||||
key: coverage-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/contract-wrappers-test/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-order-utils-{{ checksum "yarn.lock" }}
|
||||
key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/order-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-web3-wrapper-{{ checksum "yarn.lock" }}
|
||||
key: coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/web3-wrapper/coverage/lcov.info
|
||||
static-tests:
|
||||
resource_class: large
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: node:16
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- run:
|
||||
command: yarn lerna run lint
|
||||
- run:
|
||||
command: yarn prettier:ci
|
||||
- run:
|
||||
command: yarn deps_versions:ci
|
||||
- run:
|
||||
command: yarn diff_md_docs:ci
|
||||
- run:
|
||||
command: yarn test:links
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn lerna run lint
|
||||
- run: yarn prettier:ci
|
||||
- run: yarn deps_versions:ci
|
||||
- run: yarn diff_md_docs:ci
|
||||
submit-coverage:
|
||||
docker:
|
||||
- image: node:16
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-{{ checksum "yarn.lock" }}-<< pipeline.parameters.cache_version >>
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- lib-{{ .Environment.CIRCLE_SHA1 }}-<< pipeline.parameters.cache_version >>
|
||||
- coverage-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contract-wrappers-test-{{ checksum "yarn.lock" }}
|
||||
- coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-order-utils-{{ checksum "yarn.lock" }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contracts-{{ checksum "yarn.lock" }}
|
||||
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn report_coverage
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -308,9 +181,6 @@ workflows:
|
||||
# - test-contracts-extra-ganache:
|
||||
# requires:
|
||||
# - build
|
||||
- test-foundry:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts-rest-ganache:
|
||||
requires:
|
||||
- build
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@@ -173,15 +173,6 @@ contracts/zero-ex/test/generated-wrappers/
|
||||
contracts/treasury/generated-wrappers/
|
||||
contracts/treasury/test/generated-wrappers/
|
||||
|
||||
# foundry artifacts
|
||||
contracts/zero-ex/foundry-artifacts/
|
||||
|
||||
# foundry cache
|
||||
contracts/zero-ex/foundry-cache/
|
||||
|
||||
# typechain wrappers
|
||||
contracts/zero-ex/typechain-wrappers/
|
||||
|
||||
# Doc README copy
|
||||
packages/*/docs/README.md
|
||||
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "contracts/zero-ex/contracts/deps/forge-std"]
|
||||
path = contracts/zero-ex/contracts/deps/forge-std
|
||||
url = https://github.com/foundry-rs/forge-std
|
@@ -60,7 +60,6 @@ lib
|
||||
/contracts/dev-utils/test/generated-wrappers
|
||||
/contracts/dev-utils/generated-artifacts
|
||||
/contracts/dev-utils/test/generated-artifacts
|
||||
/contracts/zero-ex/foundry-artifacts
|
||||
/contracts/zero-ex/generated-wrappers
|
||||
/contracts/zero-ex/test/generated-wrappers
|
||||
/contracts/zero-ex/generated-artifacts
|
||||
@@ -81,8 +80,11 @@ lib
|
||||
/contracts/erc1155/build/
|
||||
/contracts/extensions/build/
|
||||
/contracts/exchange-forwarder/build/
|
||||
/packages/asset-swapper/
|
||||
/packages/contract-wrappers/src/generated-wrappers/
|
||||
/packages/asset-swapper/generated-artifacts
|
||||
/packages/asset-swapper/generated-wrappers
|
||||
/packages/asset-swapper/test/generated-artifacts
|
||||
/packages/asset-swapper/test/generated-wrappers
|
||||
package.json
|
||||
packages/*/docs
|
||||
docs/
|
||||
*.sol
|
||||
|
14
.prettierrc
14
.prettierrc
@@ -4,17 +4,5 @@
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "**/*.sol",
|
||||
"options": {
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"singleQuote": false,
|
||||
"bracketSpacing": false
|
||||
}
|
||||
}
|
||||
]
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "solhint:recommended",
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"avoid-low-level-calls": "off",
|
||||
"avoid-tx-origin": "warn",
|
||||
"code-complexity": "off",
|
||||
"const-name-snakecase": "error",
|
||||
"function-max-lines": "off",
|
||||
"max-line-length": ["error", 120],
|
||||
"no-inline-assembly": "off",
|
||||
"quotes": ["error", "double"],
|
||||
"no-empty-blocks": "off",
|
||||
"compiler-version": "off"
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
contracts/erc20/contracts/src/ZRXToken.sol
|
18
CODEOWNERS
18
CODEOWNERS
@@ -1,18 +1,18 @@
|
||||
# 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
|
||||
|
||||
# Dev tools & setup
|
||||
# Website
|
||||
packages/asset-swapper/ @BMillman19 @fragosti @dave4506
|
||||
packages/instant/ @BMillman19 @fragosti @dave4506
|
||||
|
||||
.circleci/ @dekz
|
||||
packages/contract-addresses/ @dekz @dextracker @kyu-c
|
||||
packages/contract-artifacts/ @dekz
|
||||
packages/protocol-utils/ @dekz
|
||||
# Dev tools & setup
|
||||
.circleci/ @dorothy-zbornak
|
||||
packages/contract-addresses/ @abandeali1
|
||||
packages/contract-artifacts/ @abandeali1
|
||||
packages/order-utils/ @dorothy-zbornak
|
||||
|
||||
# Protocol/smart contracts
|
||||
|
||||
contracts/ @dekz @dextracker
|
||||
contracts/ @abandeali1 @hysz @dorothy-zbornak @mzhu25
|
||||
|
@@ -8,13 +8,13 @@ We welcome contributions from anyone on the internet and are grateful for even t
|
||||
2. Clone your fork
|
||||
3. Follow the [installation & build steps](https://github.com/0xProject/0x-tools#install-dependencies) in the repo's top-level README.
|
||||
4. Setup the recommended [Development Tooling](#development-tooling).
|
||||
5. Open a [draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) against the `development` branch and describe the change you are intending to undertake in the PR description. (see [our branch naming conventions](#branch-structure))
|
||||
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))
|
||||
|
||||
Before making the PR "Ready for review", make sure:
|
||||
Before removing the `[WIP]` tag and submitting the PR for review, make sure:
|
||||
|
||||
- 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](#fix-submit-coverage-ci-failure) for instructions on getting the `submit-coverage` test to pass on forks)
|
||||
- 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)
|
||||
|
||||
@@ -59,14 +59,16 @@ We strongly recommend you use the [VSCode](https://code.visualstudio.com/) text
|
||||
|
||||
#### Linter
|
||||
|
||||
We use [ESLint](https://eslint.org/docs/latest/) to keep our code-style consistent.
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-tools/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.
|
||||
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-tools/tree/development/packages/tslint-config) package. All other packages have it as a dependency.
|
||||
|
||||
Integrate it into your text editor:
|
||||
|
||||
- VSCode: [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
|
||||
- Atom: [ESLint](https://atom.io/packages/eslint)
|
||||
- VSCode: [vscode-tslint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint)
|
||||
- Atom: [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
|
||||
#### Auto-formatter
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
<!--- 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! -->
|
||||
|
||||
- [ ] 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.
|
||||
|
13
README.md
13
README.md
@@ -34,6 +34,7 @@ These packages are all under development. See [/contracts/README.md](/contracts/
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| [`@0x/asset-swapper`](/packages/asset-swapper) | [](https://www.npmjs.com/package/@0x/asset-swapper) | Package used to find and create aggregated swaps |
|
||||
| [`@0x/protocol-utils`](/packages/protocol-utils) | [](https://www.npmjs.com/package/@0x/protocol-utils) | A set of utilities for generating, parsing, signing and validating 0x orders |
|
||||
| [`@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 |
|
||||
@@ -81,7 +82,7 @@ yarn build
|
||||
To build a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0x/protocol-utils yarn build
|
||||
PKG=@0x/asset-swapper yarn build
|
||||
```
|
||||
|
||||
To build all contracts packages:
|
||||
@@ -104,7 +105,7 @@ To watch a specific package and all it's dependent packages:
|
||||
PKG=[NPM_PACKAGE_NAME] yarn watch
|
||||
|
||||
e.g
|
||||
PKG=@0x/protocol-utils yarn watch
|
||||
PKG=@0x/asset-swapper yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
@@ -118,7 +119,7 @@ yarn clean
|
||||
Clean a specific package
|
||||
|
||||
```bash
|
||||
PKG=@0x/protocol-utils yarn clean
|
||||
PKG=@0x/asset-swapper yarn clean
|
||||
```
|
||||
|
||||
### Rebuild
|
||||
@@ -132,7 +133,7 @@ yarn rebuild
|
||||
To re-build (clean & build) a specific package & it's deps:
|
||||
|
||||
```bash
|
||||
PKG=@0x/protocol-utils yarn rebuild
|
||||
PKG=@0x/asset-swapper yarn rebuild
|
||||
```
|
||||
|
||||
### Lint
|
||||
@@ -146,7 +147,7 @@ yarn lint
|
||||
Lint a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0x/protocol-utils yarn lint
|
||||
PKG=@0x/asset-swapper yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
@@ -160,7 +161,7 @@ yarn test
|
||||
Run a specific package's test:
|
||||
|
||||
```bash
|
||||
PKG=@0x/protocol-utils yarn test
|
||||
PKG=@0x/asset-swapper yarn test
|
||||
```
|
||||
|
||||
Run all contracts packages tests:
|
||||
|
22
contracts/.solhint.json
Normal file
22
contracts/.solhint.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "default",
|
||||
"rules": {
|
||||
"avoid-low-level-calls": false,
|
||||
"avoid-tx-origin": "warn",
|
||||
"bracket-align": false,
|
||||
"code-complexity": false,
|
||||
"compiler-fixed": 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",
|
||||
"no-empty-blocks": false
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
||||
"overrides": [],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"ignorePatterns": [
|
||||
"lib/**/*",
|
||||
"contracts/**/*",
|
||||
"generated-wrappers/**/*",
|
||||
"generated-artifacts/**/*",
|
||||
"test/generated-wrappers/**/*",
|
||||
"test/generated-artifacts/**/*"
|
||||
|
||||
],
|
||||
"rules": {}
|
||||
}
|
1
contracts/erc20/.solhintignore
Normal file
1
contracts/erc20/.solhintignore
Normal file
@@ -0,0 +1 @@
|
||||
contracts/src/ZRXToken.sol
|
@@ -1,194 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1669235113,
|
||||
"version": "3.3.53",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1668477029,
|
||||
"version": "3.3.52",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667607537,
|
||||
"version": "3.3.51",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667427402,
|
||||
"version": "3.3.50",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666645023,
|
||||
"version": "3.3.49",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666381417,
|
||||
"version": "3.3.48",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665670315,
|
||||
"version": "3.3.47",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665531940,
|
||||
"version": "3.3.46",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.3.45",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Migrate from TSLint to ESLint and fix linting errors",
|
||||
"pr": 589
|
||||
}
|
||||
],
|
||||
"timestamp": 1665013355
|
||||
},
|
||||
{
|
||||
"timestamp": 1663786955,
|
||||
"version": "3.3.44",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662998180,
|
||||
"version": "3.3.43",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662559804,
|
||||
"version": "3.3.42",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662147076,
|
||||
"version": "3.3.41",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662046042,
|
||||
"version": "3.3.40",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661462289,
|
||||
"version": "3.3.39",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661459661,
|
||||
"version": "3.3.38",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661145612,
|
||||
"version": "3.3.37",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660093941,
|
||||
"version": "3.3.36",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660073235,
|
||||
"version": "3.3.35",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1659750766,
|
||||
"version": "3.3.34",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1658950329,
|
||||
"version": "3.3.33",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1655244958,
|
||||
"version": "3.3.32",
|
||||
|
@@ -5,90 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.3.53 - _November 23, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.52 - _November 15, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.51 - _November 5, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.50 - _November 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.49 - _October 24, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.48 - _October 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.47 - _October 13, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.46 - _October 11, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.45 - _October 5, 2022_
|
||||
|
||||
* Migrate from TSLint to ESLint and fix linting errors (#589)
|
||||
|
||||
## v3.3.44 - _September 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.43 - _September 12, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.42 - _September 7, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.41 - _September 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.40 - _September 1, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.39 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.38 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.37 - _August 22, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.36 - _August 10, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.35 - _August 9, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.34 - _August 6, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.33 - _July 27, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.32 - _June 14, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -67,3 +67,7 @@ yarn lint
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
||||
|
@@ -20,9 +20,12 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./interfaces/IERC20Token.sol";
|
||||
|
||||
contract ERC20Token is IERC20Token {
|
||||
mapping(address => uint256) internal balances;
|
||||
mapping(address => mapping(address => uint256)) internal allowed;
|
||||
|
||||
contract ERC20Token is
|
||||
IERC20Token
|
||||
{
|
||||
mapping (address => uint256) internal balances;
|
||||
mapping (address => mapping (address => uint256)) internal allowed;
|
||||
|
||||
uint256 internal _totalSupply;
|
||||
|
||||
@@ -30,14 +33,27 @@ contract ERC20Token is IERC20Token {
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transfer(address _to, uint256 _value) external returns (bool) {
|
||||
require(balances[msg.sender] >= _value, "ERC20_INSUFFICIENT_BALANCE");
|
||||
require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
|
||||
function transfer(address _to, uint256 _value)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
balances[msg.sender] >= _value,
|
||||
"ERC20_INSUFFICIENT_BALANCE"
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
"UINT256_OVERFLOW"
|
||||
);
|
||||
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
|
||||
emit Transfer(msg.sender, _to, _value);
|
||||
emit Transfer(
|
||||
msg.sender,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -47,16 +63,36 @@ contract ERC20Token is IERC20Token {
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
|
||||
require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
|
||||
require(allowed[_from][msg.sender] >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
|
||||
require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
balances[_from] >= _value,
|
||||
"ERC20_INSUFFICIENT_BALANCE"
|
||||
);
|
||||
require(
|
||||
allowed[_from][msg.sender] >= _value,
|
||||
"ERC20_INSUFFICIENT_ALLOWANCE"
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
"UINT256_OVERFLOW"
|
||||
);
|
||||
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
|
||||
emit Transfer(_from, _to, _value);
|
||||
emit Transfer(
|
||||
_from,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -65,29 +101,48 @@ contract ERC20Token is IERC20Token {
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @param _value The amount of wei to be approved for transfer
|
||||
/// @return Always true if the call has enough gas to complete execution
|
||||
function approve(address _spender, uint256 _value) external returns (bool) {
|
||||
function approve(address _spender, uint256 _value)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
emit Approval(msg.sender, _spender, _value);
|
||||
emit Approval(
|
||||
msg.sender,
|
||||
_spender,
|
||||
_value
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Query total supply of token
|
||||
/// @return Total supply of token
|
||||
function totalSupply() external view returns (uint256) {
|
||||
function totalSupply()
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return _totalSupply;
|
||||
}
|
||||
|
||||
/// @dev Query the balance of owner
|
||||
/// @param _owner The address from which the balance will be retrieved
|
||||
/// @return Balance of owner
|
||||
function balanceOf(address _owner) external view returns (uint256) {
|
||||
function balanceOf(address _owner)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
/// @param _owner The address of the account owning tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address _owner, address _spender) external view returns (uint256) {
|
||||
function allowance(address _owner, address _spender)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
}
|
||||
|
@@ -22,8 +22,9 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "../src/interfaces/IERC20Token.sol";
|
||||
|
||||
|
||||
library LibERC20Token {
|
||||
bytes private constant DECIMALS_CALL_DATA = hex"313ce567";
|
||||
bytes constant private DECIMALS_CALL_DATA = hex"313ce567";
|
||||
|
||||
/// @dev Calls `IERC20Token(token).approve()`.
|
||||
/// Reverts if `false` is returned or if the return
|
||||
@@ -31,8 +32,18 @@ library LibERC20Token {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param spender The address that receives an allowance.
|
||||
/// @param allowance The allowance to set.
|
||||
function approve(address token, address spender, uint256 allowance) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(IERC20Token(0).approve.selector, spender, allowance);
|
||||
function approve(
|
||||
address token,
|
||||
address spender,
|
||||
uint256 allowance
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
IERC20Token(0).approve.selector,
|
||||
spender,
|
||||
allowance
|
||||
);
|
||||
_callWithOptionalBooleanResult(token, callData);
|
||||
}
|
||||
|
||||
@@ -43,7 +54,13 @@ library LibERC20Token {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param spender The address that receives an allowance.
|
||||
/// @param amount The minimum allowance needed.
|
||||
function approveIfBelow(address token, address spender, uint256 amount) internal {
|
||||
function approveIfBelow(
|
||||
address token,
|
||||
address spender,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
if (IERC20Token(token).allowance(address(this), spender) < amount) {
|
||||
approve(token, spender, uint256(-1));
|
||||
}
|
||||
@@ -55,8 +72,18 @@ library LibERC20Token {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param to The address that receives the tokens
|
||||
/// @param amount Number of tokens to transfer.
|
||||
function transfer(address token, address to, uint256 amount) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(IERC20Token(0).transfer.selector, to, amount);
|
||||
function transfer(
|
||||
address token,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
IERC20Token(0).transfer.selector,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
_callWithOptionalBooleanResult(token, callData);
|
||||
}
|
||||
|
||||
@@ -67,8 +94,20 @@ library LibERC20Token {
|
||||
/// @param from The owner of the tokens.
|
||||
/// @param to The address that receives the tokens
|
||||
/// @param amount Number of tokens to transfer.
|
||||
function transferFrom(address token, address from, address to, uint256 amount) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(IERC20Token(0).transferFrom.selector, from, to, amount);
|
||||
function transferFrom(
|
||||
address token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
IERC20Token(0).transferFrom.selector,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
_callWithOptionalBooleanResult(token, callData);
|
||||
}
|
||||
|
||||
@@ -76,7 +115,11 @@ library LibERC20Token {
|
||||
/// Returns `18` if the call reverts.
|
||||
/// @param token The address of the token contract.
|
||||
/// @return tokenDecimals The number of decimals places for the token.
|
||||
function decimals(address token) internal view returns (uint8 tokenDecimals) {
|
||||
function decimals(address token)
|
||||
internal
|
||||
view
|
||||
returns (uint8 tokenDecimals)
|
||||
{
|
||||
tokenDecimals = 18;
|
||||
(bool didSucceed, bytes memory resultData) = token.staticcall(DECIMALS_CALL_DATA);
|
||||
if (didSucceed && resultData.length == 32) {
|
||||
@@ -90,9 +133,17 @@ library LibERC20Token {
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @param spender The address the spender.
|
||||
/// @return allowance The allowance for a token, owner, and spender.
|
||||
function allowance(address token, address owner, address spender) internal view returns (uint256 allowance_) {
|
||||
function allowance(address token, address owner, address spender)
|
||||
internal
|
||||
view
|
||||
returns (uint256 allowance_)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = token.staticcall(
|
||||
abi.encodeWithSelector(IERC20Token(0).allowance.selector, owner, spender)
|
||||
abi.encodeWithSelector(
|
||||
IERC20Token(0).allowance.selector,
|
||||
owner,
|
||||
spender
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length == 32) {
|
||||
allowance_ = LibBytes.readUint256(resultData, 0);
|
||||
@@ -104,9 +155,16 @@ library LibERC20Token {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @return balance The token balance of an owner.
|
||||
function balanceOf(address token, address owner) internal view returns (uint256 balance) {
|
||||
function balanceOf(address token, address owner)
|
||||
internal
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = token.staticcall(
|
||||
abi.encodeWithSelector(IERC20Token(0).balanceOf.selector, owner)
|
||||
abi.encodeWithSelector(
|
||||
IERC20Token(0).balanceOf.selector,
|
||||
owner
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length == 32) {
|
||||
balance = LibBytes.readUint256(resultData, 0);
|
||||
@@ -118,7 +176,12 @@ library LibERC20Token {
|
||||
/// was returned equal to `true`.
|
||||
/// @param target The call target.
|
||||
/// @param callData The abi-encoded call data.
|
||||
function _callWithOptionalBooleanResult(address target, bytes memory callData) private {
|
||||
function _callWithOptionalBooleanResult(
|
||||
address target,
|
||||
bytes memory callData
|
||||
)
|
||||
private
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = target.call(callData);
|
||||
if (didSucceed) {
|
||||
if (resultData.length == 0) {
|
||||
|
@@ -21,26 +21,41 @@ pragma solidity ^0.5.9;
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "./UnlimitedAllowanceERC20Token.sol";
|
||||
|
||||
contract MintableERC20Token is UnlimitedAllowanceERC20Token {
|
||||
|
||||
contract MintableERC20Token is
|
||||
UnlimitedAllowanceERC20Token
|
||||
{
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Mints new tokens
|
||||
/// @param _to Address of the beneficiary that will own the minted token
|
||||
/// @param _value Amount of tokens to mint
|
||||
function _mint(address _to, uint256 _value) internal {
|
||||
function _mint(address _to, uint256 _value)
|
||||
internal
|
||||
{
|
||||
balances[_to] = _value.safeAdd(balances[_to]);
|
||||
_totalSupply = _totalSupply.safeAdd(_value);
|
||||
|
||||
emit Transfer(address(0), _to, _value);
|
||||
emit Transfer(
|
||||
address(0),
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Mints new tokens
|
||||
/// @param _owner Owner of tokens that will be burned
|
||||
/// @param _value Amount of tokens to burn
|
||||
function _burn(address _owner, uint256 _value) internal {
|
||||
function _burn(address _owner, uint256 _value)
|
||||
internal
|
||||
{
|
||||
balances[_owner] = balances[_owner].safeSub(_value);
|
||||
_totalSupply = _totalSupply.safeSub(_value);
|
||||
|
||||
emit Transfer(_owner, address(0), _value);
|
||||
emit Transfer(
|
||||
_owner,
|
||||
address(0),
|
||||
_value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -20,20 +20,38 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./ERC20Token.sol";
|
||||
|
||||
contract UnlimitedAllowanceERC20Token is ERC20Token {
|
||||
uint256 internal constant MAX_UINT = 2 ** 256 - 1;
|
||||
|
||||
/// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.
|
||||
// See https://github.com/ethereum/EIPs/issues/717
|
||||
contract UnlimitedAllowanceERC20Token is
|
||||
ERC20Token
|
||||
{
|
||||
uint256 constant internal MAX_UINT = 2**256 - 1;
|
||||
|
||||
/// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717
|
||||
/// @param _from Address to transfer from.
|
||||
/// @param _to Address to transfer to.
|
||||
/// @param _value Amount to transfer.
|
||||
/// @return Success of transfer.
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
uint256 allowance = allowed[_from][msg.sender];
|
||||
require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
|
||||
require(allowance >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
|
||||
require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
|
||||
require(
|
||||
balances[_from] >= _value,
|
||||
"ERC20_INSUFFICIENT_BALANCE"
|
||||
);
|
||||
require(
|
||||
allowance >= _value,
|
||||
"ERC20_INSUFFICIENT_ALLOWANCE"
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
"UINT256_OVERFLOW"
|
||||
);
|
||||
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
@@ -41,7 +59,11 @@ contract UnlimitedAllowanceERC20Token is ERC20Token {
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
}
|
||||
|
||||
emit Transfer(_from, _to, _value);
|
||||
emit Transfer(
|
||||
_from,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -13,55 +13,58 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract WETH9 {
|
||||
string public name = "Wrapped Ether";
|
||||
string public symbol = "WETH";
|
||||
uint8 public decimals = 18;
|
||||
string public name = "Wrapped Ether";
|
||||
string public symbol = "WETH";
|
||||
uint8 public decimals = 18;
|
||||
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Deposit(address indexed _owner, uint256 _value);
|
||||
event Withdrawal(address indexed _owner, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint _value);
|
||||
event Transfer(address indexed _from, address indexed _to, uint _value);
|
||||
event Deposit(address indexed _owner, uint _value);
|
||||
event Withdrawal(address indexed _owner, uint _value);
|
||||
|
||||
mapping(address => uint256) public balanceOf;
|
||||
mapping(address => mapping(address => uint256)) public allowance;
|
||||
mapping (address => uint) public balanceOf;
|
||||
mapping (address => mapping (address => uint)) public allowance;
|
||||
|
||||
function() external payable {
|
||||
deposit();
|
||||
}
|
||||
|
||||
function deposit() public payable {
|
||||
balanceOf[msg.sender] += msg.value;
|
||||
emit Deposit(msg.sender, msg.value);
|
||||
}
|
||||
|
||||
function withdraw(uint256 wad) public {
|
||||
function withdraw(uint wad) public {
|
||||
require(balanceOf[msg.sender] >= wad);
|
||||
balanceOf[msg.sender] -= wad;
|
||||
msg.sender.transfer(wad);
|
||||
emit Withdrawal(msg.sender, wad);
|
||||
}
|
||||
|
||||
function totalSupply() public view returns (uint256) {
|
||||
function totalSupply() public view returns (uint) {
|
||||
return address(this).balance;
|
||||
}
|
||||
|
||||
function approve(address guy, uint256 wad) public returns (bool) {
|
||||
function approve(address guy, uint wad) public returns (bool) {
|
||||
allowance[msg.sender][guy] = wad;
|
||||
emit Approval(msg.sender, guy, wad);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transfer(address dst, uint256 wad) public returns (bool) {
|
||||
function transfer(address dst, uint wad) public returns (bool) {
|
||||
return transferFrom(msg.sender, dst, wad);
|
||||
}
|
||||
|
||||
function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
|
||||
function transferFrom(address src, address dst, uint wad)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
require(balanceOf[src] >= wad);
|
||||
|
||||
if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {
|
||||
if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
|
||||
require(allowance[src][msg.sender] >= wad);
|
||||
allowance[src][msg.sender] -= wad;
|
||||
}
|
||||
@@ -75,6 +78,7 @@ contract WETH9 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
@@ -18,99 +18,105 @@
|
||||
|
||||
pragma solidity 0.4.11;
|
||||
|
||||
|
||||
contract Token {
|
||||
|
||||
/// @return total amount of tokens
|
||||
function totalSupply() constant returns (uint256 supply) {}
|
||||
function totalSupply() constant returns (uint supply) {}
|
||||
|
||||
/// @param _owner The address from which the balance will be retrieved
|
||||
/// @return The balance
|
||||
function balanceOf(address _owner) constant returns (uint256 balance) {}
|
||||
function balanceOf(address _owner) constant returns (uint balance) {}
|
||||
|
||||
/// @notice send `_value` token to `_to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transfer(address _to, uint256 _value) returns (bool success) {}
|
||||
function transfer(address _to, uint _value) returns (bool success) {}
|
||||
|
||||
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
|
||||
function transferFrom(address _from, address _to, uint _value) returns (bool success) {}
|
||||
|
||||
/// @notice `msg.sender` approves `_addr` to spend `_value` tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @param _value The amount of wei to be approved for transfer
|
||||
/// @return Whether the approval was successful or not
|
||||
function approve(address _spender, uint256 _value) returns (bool success) {}
|
||||
function approve(address _spender, uint _value) returns (bool success) {}
|
||||
|
||||
/// @param _owner The address of the account owning tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
|
||||
function allowance(address _owner, address _spender) constant returns (uint remaining) {}
|
||||
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
event Transfer(address indexed _from, address indexed _to, uint _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint _value);
|
||||
}
|
||||
|
||||
|
||||
contract ERC20Token is Token {
|
||||
function transfer(address _to, uint256 _value) returns (bool) {
|
||||
|
||||
function transfer(address _to, uint _value) returns (bool) {
|
||||
//Default assumes totalSupply can't be over max (2^256 - 1).
|
||||
if (balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]) {
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else { return false; }
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _value) returns (bool) {
|
||||
if (
|
||||
balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]
|
||||
) {
|
||||
function transferFrom(address _from, address _to, uint _value) returns (bool) {
|
||||
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]) {
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
Transfer(_from, _to, _value);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else { return false; }
|
||||
}
|
||||
|
||||
function balanceOf(address _owner) constant returns (uint256) {
|
||||
function balanceOf(address _owner) constant returns (uint) {
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
function approve(address _spender, uint256 _value) returns (bool) {
|
||||
function approve(address _spender, uint _value) returns (bool) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender) constant returns (uint256) {
|
||||
function allowance(address _owner, address _spender) constant returns (uint) {
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
mapping(address => uint256) balances;
|
||||
mapping(address => mapping(address => uint256)) allowed;
|
||||
uint256 public totalSupply;
|
||||
mapping (address => uint) balances;
|
||||
mapping (address => mapping (address => uint)) allowed;
|
||||
uint public totalSupply;
|
||||
}
|
||||
|
||||
|
||||
contract UnlimitedAllowanceToken is ERC20Token {
|
||||
uint256 constant MAX_UINT = 2 ** 256 - 1;
|
||||
|
||||
uint constant MAX_UINT = 2**256 - 1;
|
||||
|
||||
/// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.
|
||||
/// @param _from Address to transfer from.
|
||||
/// @param _to Address to transfer to.
|
||||
/// @param _value Amount to transfer.
|
||||
/// @return Success of transfer.
|
||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
||||
uint256 allowance = allowed[_from][msg.sender];
|
||||
if (balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]) {
|
||||
function transferFrom(address _from, address _to, uint _value)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
uint allowance = allowed[_from][msg.sender];
|
||||
if (balances[_from] >= _value
|
||||
&& allowance >= _value
|
||||
&& balances[_to] + _value >= balances[_to]
|
||||
) {
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
if (allowance < MAX_UINT) {
|
||||
@@ -124,13 +130,21 @@ contract UnlimitedAllowanceToken is ERC20Token {
|
||||
}
|
||||
}
|
||||
|
||||
contract ZRXToken is UnlimitedAllowanceToken {
|
||||
uint8 public constant decimals = 18;
|
||||
uint256 public totalSupply = 10 ** 27; // 1 billion tokens, 18 decimal places
|
||||
string public constant name = "0x Protocol Token";
|
||||
string public constant symbol = "ZRX";
|
||||
|
||||
function ZRXToken() public {
|
||||
contract ZRXToken is
|
||||
UnlimitedAllowanceToken
|
||||
{
|
||||
|
||||
// solhint-disable const-name-snakecase
|
||||
uint8 constant public decimals = 18;
|
||||
uint256 public totalSupply = 10**27; // 1 billion tokens, 18 decimal places
|
||||
string constant public name = "0x Protocol Token";
|
||||
string constant public symbol = "ZRX";
|
||||
// solhint-enableconst-name-snakecase
|
||||
|
||||
function ZRXToken()
|
||||
public
|
||||
{
|
||||
balances[msg.sender] = totalSupply;
|
||||
}
|
||||
}
|
||||
|
@@ -18,40 +18,70 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
contract IERC20Token {
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
contract IERC20Token {
|
||||
|
||||
// solhint-disable no-simple-event-func-name
|
||||
event Transfer(
|
||||
address indexed _from,
|
||||
address indexed _to,
|
||||
uint256 _value
|
||||
);
|
||||
|
||||
event Approval(
|
||||
address indexed _owner,
|
||||
address indexed _spender,
|
||||
uint256 _value
|
||||
);
|
||||
|
||||
/// @dev send `value` token to `to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transfer(address _to, uint256 _value) external returns (bool);
|
||||
function transfer(address _to, uint256 _value)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev `msg.sender` approves `_spender` to spend `_value` tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @param _value The amount of wei to be approved for transfer
|
||||
/// @return Always true if the call has enough gas to complete execution
|
||||
function approve(address _spender, uint256 _value) external returns (bool);
|
||||
function approve(address _spender, uint256 _value)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev Query total supply of token
|
||||
/// @return Total supply of token
|
||||
function totalSupply() external view returns (uint256);
|
||||
function totalSupply()
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @param _owner The address from which the balance will be retrieved
|
||||
/// @return Balance of owner
|
||||
function balanceOf(address _owner) external view returns (uint256);
|
||||
function balanceOf(address _owner)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @param _owner The address of the account owning tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address _owner, address _spender) external view returns (uint256);
|
||||
function allowance(address _owner, address _spender)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
}
|
||||
|
@@ -20,8 +20,14 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./IERC20Token.sol";
|
||||
|
||||
contract IEtherToken is IERC20Token {
|
||||
function deposit() public payable;
|
||||
|
||||
function withdraw(uint256 amount) public;
|
||||
contract IEtherToken is
|
||||
IERC20Token
|
||||
{
|
||||
function deposit()
|
||||
public
|
||||
payable;
|
||||
|
||||
function withdraw(uint256 amount)
|
||||
public;
|
||||
}
|
||||
|
@@ -19,45 +19,78 @@
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
|
||||
interface IERC20TokenV06 {
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
interface IERC20TokenV06 {
|
||||
|
||||
// solhint-disable no-simple-event-func-name
|
||||
event Transfer(
|
||||
address indexed from,
|
||||
address indexed to,
|
||||
uint256 value
|
||||
);
|
||||
|
||||
event Approval(
|
||||
address indexed owner,
|
||||
address indexed spender,
|
||||
uint256 value
|
||||
);
|
||||
|
||||
/// @dev send `value` token to `to` from `msg.sender`
|
||||
/// @param to The address of the recipient
|
||||
/// @param value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transfer(address to, uint256 value) external returns (bool);
|
||||
function transfer(address to, uint256 value)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param from The address of the sender
|
||||
/// @param to The address of the recipient
|
||||
/// @param value The amount of token to be transferred
|
||||
/// @return True if transfer was successful
|
||||
function transferFrom(address from, address to, uint256 value) external returns (bool);
|
||||
function transferFrom(
|
||||
address from,
|
||||
address to,
|
||||
uint256 value
|
||||
)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev `msg.sender` approves `spender` to spend `value` tokens
|
||||
/// @param spender The address of the account able to transfer the tokens
|
||||
/// @param value The amount of wei to be approved for transfer
|
||||
/// @return Always true if the call has enough gas to complete execution
|
||||
function approve(address spender, uint256 value) external returns (bool);
|
||||
function approve(address spender, uint256 value)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
/// @dev Query total supply of token
|
||||
/// @return Total supply of token
|
||||
function totalSupply() external view returns (uint256);
|
||||
function totalSupply()
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Get the balance of `owner`.
|
||||
/// @param owner The address from which the balance will be retrieved
|
||||
/// @return Balance of owner
|
||||
function balanceOf(address owner) external view returns (uint256);
|
||||
function balanceOf(address owner)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Get the allowance for `spender` to spend from `owner`.
|
||||
/// @param owner The address of the account owning tokens
|
||||
/// @param spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address owner, address spender) external view returns (uint256);
|
||||
function allowance(address owner, address spender)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Get the number of decimals this token has.
|
||||
function decimals() external view returns (uint8);
|
||||
function decimals()
|
||||
external
|
||||
view
|
||||
returns (uint8);
|
||||
}
|
||||
|
@@ -21,7 +21,10 @@ pragma solidity ^0.6.5;
|
||||
|
||||
import "./IERC20TokenV06.sol";
|
||||
|
||||
interface IEtherTokenV06 is IERC20TokenV06 {
|
||||
|
||||
interface IEtherTokenV06 is
|
||||
IERC20TokenV06
|
||||
{
|
||||
/// @dev Wrap ether.
|
||||
function deposit() external payable;
|
||||
|
||||
|
@@ -23,16 +23,27 @@ import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
|
||||
import "./IERC20TokenV06.sol";
|
||||
|
||||
|
||||
library LibERC20TokenV06 {
|
||||
bytes private constant DECIMALS_CALL_DATA = hex"313ce567";
|
||||
bytes constant private DECIMALS_CALL_DATA = hex"313ce567";
|
||||
|
||||
/// @dev Calls `IERC20TokenV06(token).approve()`.
|
||||
/// Reverts if the return data is invalid or the call reverts.
|
||||
/// @param token The address of the token contract.
|
||||
/// @param spender The address that receives an allowance.
|
||||
/// @param allowance The allowance to set.
|
||||
function compatApprove(IERC20TokenV06 token, address spender, uint256 allowance) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(token.approve.selector, spender, allowance);
|
||||
function compatApprove(
|
||||
IERC20TokenV06 token,
|
||||
address spender,
|
||||
uint256 allowance
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
token.approve.selector,
|
||||
spender,
|
||||
allowance
|
||||
);
|
||||
_callWithOptionalBooleanResult(address(token), callData);
|
||||
}
|
||||
|
||||
@@ -42,7 +53,13 @@ library LibERC20TokenV06 {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param spender The address that receives an allowance.
|
||||
/// @param amount The minimum allowance needed.
|
||||
function approveIfBelow(IERC20TokenV06 token, address spender, uint256 amount) internal {
|
||||
function approveIfBelow(
|
||||
IERC20TokenV06 token,
|
||||
address spender,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
if (token.allowance(address(this), spender) < amount) {
|
||||
compatApprove(token, spender, uint256(-1));
|
||||
}
|
||||
@@ -53,8 +70,18 @@ library LibERC20TokenV06 {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param to The address that receives the tokens
|
||||
/// @param amount Number of tokens to transfer.
|
||||
function compatTransfer(IERC20TokenV06 token, address to, uint256 amount) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(token.transfer.selector, to, amount);
|
||||
function compatTransfer(
|
||||
IERC20TokenV06 token,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
token.transfer.selector,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
_callWithOptionalBooleanResult(address(token), callData);
|
||||
}
|
||||
|
||||
@@ -64,8 +91,20 @@ library LibERC20TokenV06 {
|
||||
/// @param from The owner of the tokens.
|
||||
/// @param to The address that receives the tokens
|
||||
/// @param amount Number of tokens to transfer.
|
||||
function compatTransferFrom(IERC20TokenV06 token, address from, address to, uint256 amount) internal {
|
||||
bytes memory callData = abi.encodeWithSelector(token.transferFrom.selector, from, to, amount);
|
||||
function compatTransferFrom(
|
||||
IERC20TokenV06 token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
bytes memory callData = abi.encodeWithSelector(
|
||||
token.transferFrom.selector,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
_callWithOptionalBooleanResult(address(token), callData);
|
||||
}
|
||||
|
||||
@@ -73,7 +112,11 @@ library LibERC20TokenV06 {
|
||||
/// Returns `18` if the call reverts.
|
||||
/// @param token The address of the token contract.
|
||||
/// @return tokenDecimals The number of decimals places for the token.
|
||||
function compatDecimals(IERC20TokenV06 token) internal view returns (uint8 tokenDecimals) {
|
||||
function compatDecimals(IERC20TokenV06 token)
|
||||
internal
|
||||
view
|
||||
returns (uint8 tokenDecimals)
|
||||
{
|
||||
tokenDecimals = 18;
|
||||
(bool didSucceed, bytes memory resultData) = address(token).staticcall(DECIMALS_CALL_DATA);
|
||||
if (didSucceed && resultData.length >= 32) {
|
||||
@@ -87,13 +130,17 @@ library LibERC20TokenV06 {
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @param spender The address the spender.
|
||||
/// @return allowance_ The allowance for a token, owner, and spender.
|
||||
function compatAllowance(
|
||||
IERC20TokenV06 token,
|
||||
address owner,
|
||||
address spender
|
||||
) internal view returns (uint256 allowance_) {
|
||||
function compatAllowance(IERC20TokenV06 token, address owner, address spender)
|
||||
internal
|
||||
view
|
||||
returns (uint256 allowance_)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = address(token).staticcall(
|
||||
abi.encodeWithSelector(token.allowance.selector, owner, spender)
|
||||
abi.encodeWithSelector(
|
||||
token.allowance.selector,
|
||||
owner,
|
||||
spender
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length >= 32) {
|
||||
allowance_ = LibBytesV06.readUint256(resultData, 0);
|
||||
@@ -105,9 +152,16 @@ library LibERC20TokenV06 {
|
||||
/// @param token The address of the token contract.
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @return balance The token balance of an owner.
|
||||
function compatBalanceOf(IERC20TokenV06 token, address owner) internal view returns (uint256 balance) {
|
||||
function compatBalanceOf(IERC20TokenV06 token, address owner)
|
||||
internal
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = address(token).staticcall(
|
||||
abi.encodeWithSelector(token.balanceOf.selector, owner)
|
||||
abi.encodeWithSelector(
|
||||
token.balanceOf.selector,
|
||||
owner
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length >= 32) {
|
||||
balance = LibBytesV06.readUint256(resultData, 0);
|
||||
@@ -119,7 +173,12 @@ library LibERC20TokenV06 {
|
||||
/// was returned equal to `true`.
|
||||
/// @param target The call target.
|
||||
/// @param callData The abi-encoded call data.
|
||||
function _callWithOptionalBooleanResult(address target, bytes memory callData) private {
|
||||
function _callWithOptionalBooleanResult(
|
||||
address target,
|
||||
bytes memory callData
|
||||
)
|
||||
private
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = target.call(callData);
|
||||
// Revert if the call reverted.
|
||||
if (!didSucceed) {
|
||||
@@ -129,9 +188,7 @@ library LibERC20TokenV06 {
|
||||
// does not return a boolean. Check that it at least contains code.
|
||||
if (resultData.length == 0) {
|
||||
uint256 size;
|
||||
assembly {
|
||||
size := extcodesize(target)
|
||||
}
|
||||
assembly { size := extcodesize(target) }
|
||||
require(size > 0, "invalid token address, contains no code");
|
||||
return;
|
||||
}
|
||||
|
@@ -22,7 +22,11 @@ import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/Ownable.sol";
|
||||
import "../src/MintableERC20Token.sol";
|
||||
|
||||
contract DummyERC20Token is Ownable, MintableERC20Token {
|
||||
|
||||
contract DummyERC20Token is
|
||||
Ownable,
|
||||
MintableERC20Token
|
||||
{
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
string public name;
|
||||
@@ -30,7 +34,14 @@ contract DummyERC20Token is Ownable, MintableERC20Token {
|
||||
uint256 public decimals;
|
||||
uint256 public constant MAX_MINT_AMOUNT = 10000000000000000000000;
|
||||
|
||||
constructor(string memory _name, string memory _symbol, uint256 _decimals, uint256 _totalSupply) public {
|
||||
constructor (
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals,
|
||||
uint256 _totalSupply
|
||||
)
|
||||
public
|
||||
{
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
decimals = _decimals;
|
||||
@@ -41,7 +52,10 @@ contract DummyERC20Token is Ownable, MintableERC20Token {
|
||||
/// @dev Sets the balance of target address
|
||||
/// @param _target Address or which balance will be updated
|
||||
/// @param _value New balance of target address
|
||||
function setBalance(address _target, uint256 _value) external onlyOwner {
|
||||
function setBalance(address _target, uint256 _value)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
uint256 currBalance = balances[_target];
|
||||
if (_value < currBalance) {
|
||||
_totalSupply = _totalSupply.safeSub(currBalance.safeSub(_value));
|
||||
@@ -53,8 +67,13 @@ contract DummyERC20Token is Ownable, MintableERC20Token {
|
||||
|
||||
/// @dev Mints new tokens for sender
|
||||
/// @param _value Amount of tokens to mint
|
||||
function mint(uint256 _value) external {
|
||||
require(_value <= MAX_MINT_AMOUNT, "VALUE_TOO_LARGE");
|
||||
function mint(uint256 _value)
|
||||
external
|
||||
{
|
||||
require(
|
||||
_value <= MAX_MINT_AMOUNT,
|
||||
"VALUE_TOO_LARGE"
|
||||
);
|
||||
|
||||
_mint(msg.sender, _value);
|
||||
}
|
||||
|
@@ -20,23 +20,45 @@ pragma solidity ^0.5.5;
|
||||
|
||||
import "./DummyERC20Token.sol";
|
||||
|
||||
contract DummyMultipleReturnERC20Token is DummyERC20Token {
|
||||
constructor(
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract DummyMultipleReturnERC20Token is
|
||||
DummyERC20Token
|
||||
{
|
||||
constructor (
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals,
|
||||
uint256 _totalSupply
|
||||
) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
|
||||
)
|
||||
public
|
||||
DummyERC20Token(
|
||||
_name,
|
||||
_symbol,
|
||||
_decimals,
|
||||
_totalSupply
|
||||
)
|
||||
{}
|
||||
|
||||
/// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
|
||||
emit Transfer(_from, _to, _value);
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
emit Transfer(
|
||||
_from,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
// HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes
|
||||
// (equiavalent to true, true)
|
||||
// HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes (equiavalent to true, true)
|
||||
assembly {
|
||||
mstore(0, 1)
|
||||
mstore(32, 1)
|
||||
@@ -44,3 +66,4 @@ contract DummyMultipleReturnERC20Token is DummyERC20Token {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,25 +20,50 @@ pragma solidity ^0.5.5;
|
||||
|
||||
import "./DummyERC20Token.sol";
|
||||
|
||||
contract DummyNoReturnERC20Token is DummyERC20Token {
|
||||
constructor(
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract DummyNoReturnERC20Token is
|
||||
DummyERC20Token
|
||||
{
|
||||
constructor (
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals,
|
||||
uint256 _totalSupply
|
||||
) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
|
||||
)
|
||||
public
|
||||
DummyERC20Token(
|
||||
_name,
|
||||
_symbol,
|
||||
_decimals,
|
||||
_totalSupply
|
||||
)
|
||||
{}
|
||||
|
||||
/// @dev send `value` token to `to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
function transfer(address _to, uint256 _value) external returns (bool) {
|
||||
require(balances[msg.sender] >= _value, "ERC20_INSUFFICIENT_BALANCE");
|
||||
require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
|
||||
function transfer(address _to, uint256 _value)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
balances[msg.sender] >= _value,
|
||||
"ERC20_INSUFFICIENT_BALANCE"
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
"UINT256_OVERFLOW"
|
||||
);
|
||||
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
|
||||
emit Transfer(msg.sender, _to, _value);
|
||||
emit Transfer(
|
||||
msg.sender,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
// HACK: This contract will not compile if we remove `returns (bool)`, so we manually return no data
|
||||
assembly {
|
||||
@@ -50,16 +75,36 @@ contract DummyNoReturnERC20Token is DummyERC20Token {
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
|
||||
require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
|
||||
require(allowed[_from][msg.sender] >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
|
||||
require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
balances[_from] >= _value,
|
||||
"ERC20_INSUFFICIENT_BALANCE"
|
||||
);
|
||||
require(
|
||||
allowed[_from][msg.sender] >= _value,
|
||||
"ERC20_INSUFFICIENT_ALLOWANCE"
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
"UINT256_OVERFLOW"
|
||||
);
|
||||
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
|
||||
emit Transfer(_from, _to, _value);
|
||||
|
||||
emit Transfer(
|
||||
_from,
|
||||
_to,
|
||||
_value
|
||||
);
|
||||
|
||||
// HACK: This contract will not compile if we remove `returns (bool)`, so we manually return no data
|
||||
assembly {
|
||||
@@ -67,3 +112,4 @@ contract DummyNoReturnERC20Token is DummyERC20Token {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,9 @@ pragma solidity ^0.5.9;
|
||||
import "../src/LibERC20Token.sol";
|
||||
import "./TestLibERC20TokenTarget.sol";
|
||||
|
||||
|
||||
contract TestLibERC20Token {
|
||||
|
||||
TestLibERC20TokenTarget public target;
|
||||
|
||||
constructor() public {
|
||||
@@ -34,7 +36,9 @@ contract TestLibERC20Token {
|
||||
bytes calldata returnData,
|
||||
address spender,
|
||||
uint256 allowance
|
||||
) external {
|
||||
)
|
||||
external
|
||||
{
|
||||
target.setBehavior(shouldRevert, revertData, returnData);
|
||||
LibERC20Token.approve(address(target), spender, allowance);
|
||||
}
|
||||
@@ -45,7 +49,9 @@ contract TestLibERC20Token {
|
||||
bytes calldata returnData,
|
||||
address to,
|
||||
uint256 amount
|
||||
) external {
|
||||
)
|
||||
external
|
||||
{
|
||||
target.setBehavior(shouldRevert, revertData, returnData);
|
||||
LibERC20Token.transfer(address(target), to, amount);
|
||||
}
|
||||
@@ -57,7 +63,9 @@ contract TestLibERC20Token {
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) external {
|
||||
)
|
||||
external
|
||||
{
|
||||
target.setBehavior(shouldRevert, revertData, returnData);
|
||||
LibERC20Token.transferFrom(address(target), from, to, amount);
|
||||
}
|
||||
@@ -66,7 +74,10 @@ contract TestLibERC20Token {
|
||||
bool shouldRevert,
|
||||
bytes calldata revertData,
|
||||
bytes calldata returnData
|
||||
) external returns (uint8) {
|
||||
)
|
||||
external
|
||||
returns (uint8)
|
||||
{
|
||||
target.setBehavior(shouldRevert, revertData, returnData);
|
||||
return LibERC20Token.decimals(address(target));
|
||||
}
|
||||
|
@@ -18,52 +18,89 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract TestLibERC20TokenTarget {
|
||||
event ApproveCalled(address spender, uint256 allowance);
|
||||
|
||||
event TransferCalled(address to, uint256 amount);
|
||||
event ApproveCalled(
|
||||
address spender,
|
||||
uint256 allowance
|
||||
);
|
||||
|
||||
event TransferFromCalled(address from, address to, uint256 amount);
|
||||
event TransferCalled(
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
event TransferFromCalled(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
bool private _shouldRevert;
|
||||
bytes private _revertData;
|
||||
bytes private _returnData;
|
||||
|
||||
function setBehavior(bool shouldRevert, bytes calldata revertData, bytes calldata returnData) external {
|
||||
function setBehavior(
|
||||
bool shouldRevert,
|
||||
bytes calldata revertData,
|
||||
bytes calldata returnData
|
||||
)
|
||||
external
|
||||
{
|
||||
_shouldRevert = shouldRevert;
|
||||
_revertData = revertData;
|
||||
_returnData = returnData;
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 allowance) external returns (bool) {
|
||||
function approve(
|
||||
address spender,
|
||||
uint256 allowance
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
emit ApproveCalled(spender, allowance);
|
||||
_execute();
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) external returns (bool) {
|
||||
function transfer(
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
emit TransferCalled(to, amount);
|
||||
_execute();
|
||||
}
|
||||
|
||||
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
|
||||
function transferFrom(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
emit TransferFromCalled(from, to, amount);
|
||||
_execute();
|
||||
}
|
||||
|
||||
function decimals() external view returns (uint8) {
|
||||
function decimals()
|
||||
external
|
||||
view
|
||||
returns (uint8)
|
||||
{
|
||||
_execute();
|
||||
}
|
||||
|
||||
function _execute() private view {
|
||||
if (_shouldRevert) {
|
||||
bytes memory revertData = _revertData;
|
||||
assembly {
|
||||
revert(add(revertData, 0x20), mload(revertData))
|
||||
}
|
||||
assembly { revert(add(revertData, 0x20), mload(revertData)) }
|
||||
}
|
||||
bytes memory returnData = _returnData;
|
||||
assembly {
|
||||
return(add(returnData, 0x20), mload(returnData))
|
||||
}
|
||||
assembly { return(add(returnData, 0x20), mload(returnData)) }
|
||||
}
|
||||
}
|
||||
|
@@ -20,19 +20,43 @@ pragma solidity ^0.5.5;
|
||||
|
||||
import "./DummyERC20Token.sol";
|
||||
|
||||
contract UntransferrableDummyERC20Token is DummyERC20Token {
|
||||
constructor(
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
// solhint-disable no-unused-vars
|
||||
contract UntransferrableDummyERC20Token is
|
||||
DummyERC20Token
|
||||
{
|
||||
constructor (
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals,
|
||||
uint256 _totalSupply
|
||||
) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
|
||||
)
|
||||
public
|
||||
DummyERC20Token(
|
||||
_name,
|
||||
_symbol,
|
||||
_decimals,
|
||||
_totalSupply
|
||||
)
|
||||
{}
|
||||
|
||||
/// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
|
||||
require(false, "TRANSFER_DISABLED");
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
require(
|
||||
false,
|
||||
"TRANSFER_DISABLED"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc20",
|
||||
"version": "3.3.53",
|
||||
"version": "3.3.32",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -23,8 +23,8 @@
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
|
||||
"lint": "eslint src test",
|
||||
"fix": "eslint --fix src test",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/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",
|
||||
@@ -32,6 +32,7 @@
|
||||
"test:circleci": "yarn test",
|
||||
"contracts:gen": "contracts-gen generate",
|
||||
"contracts:copy": "contracts-gen copy",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
|
||||
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||
},
|
||||
@@ -50,39 +51,38 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.8.1",
|
||||
"@0x/contracts-gen": "^2.0.48",
|
||||
"@0x/contracts-test-utils": "^5.4.43",
|
||||
"@0x/contracts-utils": "^4.8.34",
|
||||
"@0x/dev-utils": "^5.0.0",
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
"@0x/abi-gen": "^5.8.0",
|
||||
"@0x/contracts-gen": "^2.0.46",
|
||||
"@0x/contracts-test-utils": "^5.4.23",
|
||||
"@0x/contracts-utils": "^4.8.13",
|
||||
"@0x/dev-utils": "^4.2.14",
|
||||
"@0x/sol-compiler": "^4.8.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.6",
|
||||
"@0x/typescript-typings": "^5.3.1",
|
||||
"@0x/utils": "^7.0.0",
|
||||
"@0x/web3-wrapper": "^8.0.0",
|
||||
"@0x/utils": "^6.5.3",
|
||||
"@0x/web3-wrapper": "^7.6.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "12.12.54",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||
"@typescript-eslint/parser": "^5.38.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"ethereum-types": "^3.7.1",
|
||||
"ethereum-types": "^3.7.0",
|
||||
"lodash": "^4.17.11",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "~0.16.11",
|
||||
"typescript": "4.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/base-contract": "^6.5.0",
|
||||
"ethers": "~4.0.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -15,7 +15,7 @@ export const artifacts = {
|
||||
DummyERC20Token: DummyERC20Token as ContractArtifact,
|
||||
ERC20Token: ERC20Token as ContractArtifact,
|
||||
WETH9: WETH9 as ContractArtifact,
|
||||
ZRXToken: ZRXToken as any as ContractArtifact,
|
||||
ZRXToken: (ZRXToken as any) as ContractArtifact,
|
||||
DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
|
||||
DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
|
||||
};
|
||||
|
@@ -28,7 +28,7 @@ export const artifacts = {
|
||||
MintableERC20Token: MintableERC20Token as ContractArtifact,
|
||||
UnlimitedAllowanceERC20Token: UnlimitedAllowanceERC20Token as ContractArtifact,
|
||||
WETH9: WETH9 as ContractArtifact,
|
||||
ZRXToken: ZRXToken as any as ContractArtifact,
|
||||
ZRXToken: (ZRXToken as any) as ContractArtifact,
|
||||
IERC20Token: IERC20Token as ContractArtifact,
|
||||
IEtherToken: IEtherToken as ContractArtifact,
|
||||
IERC20TokenV06: IERC20TokenV06 as ContractArtifact,
|
||||
|
6
contracts/erc20/tslint.json
Normal file
6
contracts/erc20/tslint.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
||||
"overrides": [],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"ignorePatterns": [
|
||||
"lib/**/*",
|
||||
"contracts/**/*",
|
||||
"generated-wrappers/**/*",
|
||||
"generated-artifacts/**/*",
|
||||
"test/generated-wrappers/**/*",
|
||||
"test/generated-artifacts/**/*"
|
||||
|
||||
],
|
||||
"rules": {}
|
||||
}
|
@@ -1,185 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1669235113,
|
||||
"version": "5.4.43",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1668477029,
|
||||
"version": "5.4.42",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667607537,
|
||||
"version": "5.4.41",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667427402,
|
||||
"version": "5.4.40",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666645023,
|
||||
"version": "5.4.39",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666381417,
|
||||
"version": "5.4.38",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665531940,
|
||||
"version": "5.4.37",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "5.4.36",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Migrate from TSLint to ESLint and fix linting errors",
|
||||
"pr": 589
|
||||
}
|
||||
],
|
||||
"timestamp": 1665013355
|
||||
},
|
||||
{
|
||||
"timestamp": 1663786955,
|
||||
"version": "5.4.35",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662998180,
|
||||
"version": "5.4.34",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662559804,
|
||||
"version": "5.4.33",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662147076,
|
||||
"version": "5.4.32",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662046042,
|
||||
"version": "5.4.31",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661462289,
|
||||
"version": "5.4.30",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661459661,
|
||||
"version": "5.4.29",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661145612,
|
||||
"version": "5.4.28",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660093941,
|
||||
"version": "5.4.27",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660073235,
|
||||
"version": "5.4.26",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1659750766,
|
||||
"version": "5.4.25",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1658950329,
|
||||
"version": "5.4.24",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1655244958,
|
||||
"version": "5.4.23",
|
||||
|
@@ -5,86 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.4.43 - _November 23, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.42 - _November 15, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.41 - _November 5, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.40 - _November 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.39 - _October 24, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.38 - _October 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.37 - _October 11, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.36 - _October 5, 2022_
|
||||
|
||||
* Migrate from TSLint to ESLint and fix linting errors (#589)
|
||||
|
||||
## v5.4.35 - _September 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.34 - _September 12, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.33 - _September 7, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.32 - _September 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.31 - _September 1, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.30 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.29 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.28 - _August 22, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.27 - _August 10, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.26 - _August 9, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.25 - _August 6, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.24 - _July 27, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.23 - _June 14, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-test-utils",
|
||||
"version": "5.4.43",
|
||||
"version": "5.4.23",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -16,8 +16,8 @@
|
||||
"test:coverage": "run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||
"clean": "shx rm -rf lib",
|
||||
"lint": "eslint src test",
|
||||
"fix": "eslint --fix src test",
|
||||
"lint": "tslint --format stylish --project tsconfig.lint.json",
|
||||
"fix": "tslint --fix --format stylish --project tsconfig.lint.json",
|
||||
"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",
|
||||
@@ -34,30 +34,28 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/test-utils",
|
||||
"devDependencies": {
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||
"@typescript-eslint/parser": "^5.38.0",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"@0x/sol-compiler": "^4.8.1",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "4.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.35",
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/contract-addresses": "^7.4.1",
|
||||
"@0x/dev-utils": "^5.0.0",
|
||||
"@0x/assert": "^3.0.34",
|
||||
"@0x/base-contract": "^6.5.0",
|
||||
"@0x/contract-addresses": "^6.16.0",
|
||||
"@0x/dev-utils": "^4.2.14",
|
||||
"@0x/json-schemas": "^6.4.4",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-coverage": "^4.0.46",
|
||||
"@0x/sol-profiler": "^4.1.36",
|
||||
"@0x/sol-trace": "^3.0.46",
|
||||
"@0x/subproviders": "^7.0.0",
|
||||
"@0x/sol-coverage": "^4.0.45",
|
||||
"@0x/sol-profiler": "^4.1.35",
|
||||
"@0x/sol-trace": "^3.0.45",
|
||||
"@0x/subproviders": "^6.6.5",
|
||||
"@0x/types": "^3.3.6",
|
||||
"@0x/typescript-typings": "^5.3.1",
|
||||
"@0x/utils": "^7.0.0",
|
||||
"@0x/web3-wrapper": "^8.0.0",
|
||||
"@0x/utils": "^6.5.3",
|
||||
"@0x/web3-wrapper": "^7.6.5",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"@types/lodash": "4.14.104",
|
||||
@@ -69,7 +67,7 @@
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"decimal.js": "^10.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereum-types": "^3.7.1",
|
||||
"ethereum-types": "^3.7.0",
|
||||
"ethereumjs-util": "^7.0.10",
|
||||
"ethers": "~4.0.4",
|
||||
"js-combinatorics": "^0.5.3",
|
||||
|
@@ -38,7 +38,7 @@ async function _getGanacheOrGethErrorAsync(ganacheError: string, gethError: stri
|
||||
}
|
||||
|
||||
async function _getInsufficientFundsErrorMessageAsync(): Promise<string> {
|
||||
return _getGanacheOrGethErrorAsync('insufficient funds for gas * price + value', 'insufficient funds');
|
||||
return _getGanacheOrGethErrorAsync("sender doesn't have enough funds", 'insufficient funds');
|
||||
}
|
||||
|
||||
async function _getTransactionFailedErrorMessageAsync(): Promise<string> {
|
||||
@@ -102,9 +102,9 @@ export async function expectTransactionFailedAsync(p: sendTransactionResult, rea
|
||||
if (nodeType === undefined) {
|
||||
nodeType = await web3Wrapper.getNodeTypeAsync();
|
||||
}
|
||||
const rejectionMessageRegex = new RegExp(`^VM Exception while processing transaction: revert ${reason}$`);
|
||||
switch (nodeType) {
|
||||
case NodeType.Ganache:
|
||||
const rejectionMessageRegex = new RegExp(`^VM Exception while processing transaction: revert ${reason}$`);
|
||||
return expect(p).to.be.rejectedWith(rejectionMessageRegex);
|
||||
case NodeType.Geth:
|
||||
logUtils.warn(
|
||||
|
@@ -11,14 +11,9 @@ export function shortZip<T1, T2>(a: T1[], b: T2[]): Array<[T1, T2]> {
|
||||
/**
|
||||
* Replaces the keys in a deeply nested object. Adapted from https://stackoverflow.com/a/39126851
|
||||
*/
|
||||
export function replaceKeysDeep(
|
||||
obj: Record<string, unknown>,
|
||||
mapKeys: (key: string) => string | void,
|
||||
): _.Dictionary<Record<string, unknown>> {
|
||||
export function replaceKeysDeep(obj: {}, mapKeys: (key: string) => string | void): _.Dictionary<{}> {
|
||||
return _.transform(obj, (result, value, key) => {
|
||||
const currentKey = mapKeys(key) || key;
|
||||
result[currentKey] = _.isObject(value)
|
||||
? replaceKeysDeep(value as Record<string, unknown>, mapKeys)
|
||||
: (value as Record<string, unknown>);
|
||||
result[currentKey] = _.isObject(value) ? replaceKeysDeep(value as {}, mapKeys) : (value as {});
|
||||
});
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@ export class LogDecoder {
|
||||
}
|
||||
public decodeLogOrThrow<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog {
|
||||
const logWithDecodedArgsOrLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
if ((logWithDecodedArgsOrLog as LogWithDecodedArgs<ArgsType>).args === undefined) {
|
||||
throw new Error(`Unable to decode log: ${JSON.stringify(log)}`);
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@ import { LogEntry, LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from
|
||||
|
||||
import { expect } from './chai_setup';
|
||||
|
||||
// tslint:disable no-unnecessary-type-assertion
|
||||
|
||||
/**
|
||||
* Filter logs by event name/type.
|
||||
*/
|
||||
|
@@ -8,6 +8,8 @@ import * as process from 'process';
|
||||
|
||||
import { provider, providerConfigs, txDefaults, web3Wrapper } from './web3_wrapper';
|
||||
|
||||
// tslint:disable: no-namespace only-arrow-functions no-unbound-method max-classes-per-file
|
||||
|
||||
export type ISuite = mocha.ISuite;
|
||||
export type ISuiteCallbackContext = mocha.ISuiteCallbackContext;
|
||||
export type SuiteCallback = (this: ISuiteCallbackContext) => void;
|
||||
@@ -234,7 +236,7 @@ export const describe = _.assign(mochaDescribe, {
|
||||
* Like mocha's `describe()`, but sets up a blockchain environment for you.
|
||||
*/
|
||||
export const blockchainTests: BlockchainContextDefinition = _.assign(
|
||||
function (description: string, callback: BlockchainSuiteCallback): ISuite {
|
||||
function(description: string, callback: BlockchainSuiteCallback): ISuite {
|
||||
return defineBlockchainSuite(StandardBlockchainTestsEnvironmentSingleton, description, callback, describe);
|
||||
},
|
||||
{
|
||||
@@ -273,7 +275,7 @@ export const blockchainTests: BlockchainContextDefinition = _.assign(
|
||||
);
|
||||
},
|
||||
fork: _.assign(
|
||||
function (description: string, callback: BlockchainSuiteCallback): ISuite | void {
|
||||
function(description: string, callback: BlockchainSuiteCallback): ISuite | void {
|
||||
return defineBlockchainSuite(
|
||||
ForkedBlockchainTestsEnvironmentSingleton,
|
||||
description,
|
||||
@@ -317,7 +319,7 @@ export const blockchainTests: BlockchainContextDefinition = _.assign(
|
||||
},
|
||||
),
|
||||
live: _.assign(
|
||||
function (description: string, callback: BlockchainSuiteCallback): ISuite | void {
|
||||
function(description: string, callback: BlockchainSuiteCallback): ISuite | void {
|
||||
return defineBlockchainSuite(
|
||||
LiveBlockchainTestsEnvironmentSingleton,
|
||||
description,
|
||||
@@ -353,7 +355,7 @@ export const blockchainTests: BlockchainContextDefinition = _.assign(
|
||||
},
|
||||
),
|
||||
resets: _.assign(
|
||||
function (description: string, callback: BlockchainSuiteCallback): ISuite {
|
||||
function(description: string, callback: BlockchainSuiteCallback): ISuite {
|
||||
return defineResetsBlockchainSuite(
|
||||
StandardBlockchainTestsEnvironmentSingleton,
|
||||
description,
|
||||
@@ -397,7 +399,7 @@ function defineBlockchainSuite<T>(
|
||||
callback: BlockchainSuiteCallback,
|
||||
describeCall: ContextDefinitionCallback<T>,
|
||||
): T {
|
||||
return describeCall(description, function (this: ISuiteCallbackContext): void {
|
||||
return describeCall(description, function(this: ISuiteCallbackContext): void {
|
||||
callback.call(this, envFactory.create());
|
||||
});
|
||||
}
|
||||
@@ -408,7 +410,7 @@ function defineResetsBlockchainSuite<T>(
|
||||
callback: BlockchainSuiteCallback,
|
||||
describeCall: ContextDefinitionCallback<T>,
|
||||
): T {
|
||||
return describeCall(description, function (this: ISuiteCallbackContext): void {
|
||||
return describeCall(description, function(this: ISuiteCallbackContext): void {
|
||||
const env = envFactory.create();
|
||||
beforeEach(async () => env.blockchainLifecycle.startAsync());
|
||||
afterEach(async () => env.blockchainLifecycle.revertAsync());
|
||||
|
@@ -40,7 +40,10 @@ export function getRandomPortion(total: Numberish): BigNumber {
|
||||
export function getRandomFloat(min: Numberish, max: Numberish): BigNumber {
|
||||
// Generate a really high precision number between [0, 1]
|
||||
const r = new BigNumber(crypto.randomBytes(32).toString('hex'), 16).dividedBy(new BigNumber(2).pow(256).minus(1));
|
||||
return new BigNumber(max).minus(min).times(r).plus(min);
|
||||
return new BigNumber(max)
|
||||
.minus(min)
|
||||
.times(r)
|
||||
.plus(min);
|
||||
}
|
||||
|
||||
export const FIXED_POINT_BASE = new BigNumber(2).pow(127);
|
||||
@@ -63,7 +66,7 @@ export function fromFixed(n: Numberish): BigNumber {
|
||||
* Converts two decimal numbers to integers with `precision` digits, then returns
|
||||
* the absolute difference.
|
||||
*/
|
||||
export function getNumericalDivergence(a: Numberish, b: Numberish, precision = 18): number {
|
||||
export function getNumericalDivergence(a: Numberish, b: Numberish, precision: number = 18): number {
|
||||
const _a = new BigNumber(a);
|
||||
const _b = new BigNumber(b);
|
||||
const maxIntegerDigits = Math.max(
|
||||
@@ -74,13 +77,16 @@ export function getNumericalDivergence(a: Numberish, b: Numberish, precision = 1
|
||||
const base = 10 ** (precision - maxIntegerDigits);
|
||||
return n.times(base).integerValue(BigNumber.ROUND_DOWN);
|
||||
};
|
||||
return _toInteger(_a).minus(_toInteger(_b)).abs().toNumber();
|
||||
return _toInteger(_a)
|
||||
.minus(_toInteger(_b))
|
||||
.abs()
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two numbers are equal up to `precision` digits.
|
||||
*/
|
||||
export function assertRoughlyEquals(actual: Numberish, expected: Numberish, precision = 18): void {
|
||||
export function assertRoughlyEquals(actual: Numberish, expected: Numberish, precision: number = 18): void {
|
||||
if (getNumericalDivergence(actual, expected, precision) <= 1) {
|
||||
return;
|
||||
}
|
||||
@@ -90,8 +96,16 @@ export function assertRoughlyEquals(actual: Numberish, expected: Numberish, prec
|
||||
/**
|
||||
* Asserts that two numbers are equal with up to `maxError` difference between them.
|
||||
*/
|
||||
export function assertIntegerRoughlyEquals(actual: Numberish, expected: Numberish, maxError = 1, msg?: string): void {
|
||||
const diff = new BigNumber(actual).minus(expected).abs().toNumber();
|
||||
export function assertIntegerRoughlyEquals(
|
||||
actual: Numberish,
|
||||
expected: Numberish,
|
||||
maxError: number = 1,
|
||||
msg?: string,
|
||||
): void {
|
||||
const diff = new BigNumber(actual)
|
||||
.minus(expected)
|
||||
.abs()
|
||||
.toNumber();
|
||||
if (diff <= maxError) {
|
||||
return;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ export class OrderFactory {
|
||||
salt: generatePseudoRandomSalt(),
|
||||
...this._defaultOrderParams,
|
||||
...customOrderParams,
|
||||
} as Order;
|
||||
} as Order; // tslint:disable-line:no-object-literal-type-assertion
|
||||
const orderHashBuff = orderHashUtils.getOrderHashBuffer(order);
|
||||
const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType);
|
||||
const signedOrder = {
|
||||
|
@@ -8,7 +8,10 @@ import { BatchMatchOrder, CancelOrder, MatchOrder } from './types';
|
||||
|
||||
export const orderUtils = {
|
||||
getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
const partialAmount = numerator.multipliedBy(target).div(denominator).integerValue(BigNumber.ROUND_FLOOR);
|
||||
const partialAmount = numerator
|
||||
.multipliedBy(target)
|
||||
.div(denominator)
|
||||
.integerValue(BigNumber.ROUND_FLOOR);
|
||||
return partialAmount;
|
||||
},
|
||||
createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => {
|
||||
|
@@ -9,6 +9,7 @@ export const typeEncodingUtils = {
|
||||
const base = 10;
|
||||
const formattedValue = new BN(value.toString(base));
|
||||
const encodedValue = ethUtil.toBuffer(formattedValue);
|
||||
// tslint:disable-next-line:custom-no-magic-numbers
|
||||
const paddedValue = ethUtil.setLengthLeft(encodedValue, constants.WORD_LENGTH);
|
||||
return paddedValue;
|
||||
},
|
||||
|
@@ -15,7 +15,7 @@ export const txDefaults = {
|
||||
gasPrice: constants.DEFAULT_GAS_PRICE,
|
||||
};
|
||||
|
||||
export const providerConfigs: Web3Config = {
|
||||
export let providerConfigs: Web3Config = {
|
||||
total_accounts: constants.NUM_TEST_ACCOUNTS,
|
||||
shouldUseInProcessGanache: true,
|
||||
shouldAllowUnlimitedContractSize: true,
|
||||
|
@@ -4,7 +4,6 @@ import * as process from 'process';
|
||||
import { expect } from '../src/chai_setup';
|
||||
import { constants } from '../src/constants';
|
||||
import { blockchainTests, describe } from '../src/mocha_blockchain';
|
||||
import { append } from './subtests/mocha_blockchain_1';
|
||||
|
||||
blockchainTests('mocha blockchain extensions', env => {
|
||||
describe('blockchainTests()', () => {
|
||||
@@ -13,8 +12,11 @@ blockchainTests('mocha blockchain extensions', env => {
|
||||
expect(env.provider).to.exist('');
|
||||
expect(env.txDefaults).to.exist('');
|
||||
expect(env.web3Wrapper).to.exist('');
|
||||
// HACK(dorothy-zbornak): tslint seems to get confused by these assertions.
|
||||
// tslint:disable: no-unbound-method
|
||||
expect(typeof env.getChainIdAsync).to.eq('function');
|
||||
expect(typeof env.getAccountAddressesAsync).to.eq('function');
|
||||
// tslint:enable: no-unbound-method
|
||||
});
|
||||
|
||||
it('initializes the test environment', async () => {
|
||||
@@ -76,7 +78,7 @@ blockchainTests('mocha blockchain extensions', env => {
|
||||
});
|
||||
|
||||
describe('subtests', () => {
|
||||
append(env);
|
||||
require('./subtests/mocha_blockchain_1').append(env);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,7 +95,8 @@ blockchainTests('mocha blockchain extensions', env => {
|
||||
|
||||
function createHookedObject(obj: any, handler: (name: string) => void, methods: string[]): any {
|
||||
const hookedMethods = _.map(methods, methodName => {
|
||||
return function (this: any, ...args: any[]): any {
|
||||
// tslint:disable: only-arrow-functions
|
||||
return function(this: any, ...args: any[]): any {
|
||||
handler(methodName);
|
||||
return obj[methodName].call(this, ...args);
|
||||
};
|
||||
|
@@ -42,6 +42,7 @@ describe('Order hashing', () => {
|
||||
// It's common for developers using javascript to provide the amounts
|
||||
// as strings. Since we eventually toString() the BigNumber
|
||||
// before encoding we should result in the same orderHash in this scenario
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const orderHash = orderHashUtils.getOrderHashHex({
|
||||
...order,
|
||||
makerAssetAmount: '0',
|
||||
@@ -54,7 +55,7 @@ describe('Order hashing', () => {
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
takerAddress: null as any as string,
|
||||
takerAddress: (null as any) as string,
|
||||
};
|
||||
const expectedErrorMessage = `Expected order to conform to schema`;
|
||||
expect(() => orderHashUtils.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { expect } from '../../src/chai_setup';
|
||||
import { blockchainTests, BlockchainTestsEnvironment } from '../../src/mocha_blockchain';
|
||||
|
||||
// tslint:disable: no-default-export completed-docs
|
||||
export function append(env: BlockchainTestsEnvironment): void {
|
||||
blockchainTests('imported subtests', subtestsEnv => {
|
||||
it('shares the same environment object', () => {
|
||||
|
@@ -35,6 +35,7 @@ describe('0x transaction hashing', () => {
|
||||
// It's common for developers using javascript to provide the amounts
|
||||
// as strings. Since we eventually toString() the BigNumber
|
||||
// before encoding we should result in the same orderHash in this scenario
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const transactionHash = transactionHashUtils.getTransactionHashHex({
|
||||
...transaction,
|
||||
salt: '0',
|
||||
|
7
contracts/test-utils/tsconfig.lint.json
Normal file
7
contracts/test-utils/tsconfig.lint.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// This file is a workaround that issue: https://github.com/palantir/tslint/issues/4148#issuecomment-419872702
|
||||
"extends": "./tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": false
|
||||
}
|
||||
}
|
6
contracts/test-utils/tslint.json
Normal file
6
contracts/test-utils/tslint.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
||||
"overrides": [],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"ignorePatterns": [
|
||||
"lib/**/*",
|
||||
"contracts/**/*",
|
||||
"generated-wrappers/**/*",
|
||||
"generated-artifacts/**/*",
|
||||
"test/generated-wrappers/**/*",
|
||||
"test/generated-artifacts/**/*"
|
||||
|
||||
],
|
||||
"rules": {}
|
||||
}
|
@@ -1,194 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1669235113,
|
||||
"version": "1.4.36",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1668477029,
|
||||
"version": "1.4.35",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667607537,
|
||||
"version": "1.4.34",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667427402,
|
||||
"version": "1.4.33",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666645023,
|
||||
"version": "1.4.32",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666381417,
|
||||
"version": "1.4.31",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665670315,
|
||||
"version": "1.4.30",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665531940,
|
||||
"version": "1.4.29",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.4.28",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Migrate from TSLint to ESLint and fix linting errors",
|
||||
"pr": 589
|
||||
}
|
||||
],
|
||||
"timestamp": 1665013355
|
||||
},
|
||||
{
|
||||
"timestamp": 1663786955,
|
||||
"version": "1.4.27",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662998180,
|
||||
"version": "1.4.26",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662559804,
|
||||
"version": "1.4.25",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662147076,
|
||||
"version": "1.4.24",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662046042,
|
||||
"version": "1.4.23",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661462289,
|
||||
"version": "1.4.22",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661459661,
|
||||
"version": "1.4.21",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661145612,
|
||||
"version": "1.4.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660093941,
|
||||
"version": "1.4.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660073235,
|
||||
"version": "1.4.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1659750766,
|
||||
"version": "1.4.17",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1658950329,
|
||||
"version": "1.4.16",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1655244958,
|
||||
"version": "1.4.15",
|
||||
|
@@ -5,90 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.4.36 - _November 23, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.35 - _November 15, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.34 - _November 5, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.33 - _November 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.32 - _October 24, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.31 - _October 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.30 - _October 13, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.29 - _October 11, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.28 - _October 5, 2022_
|
||||
|
||||
* Migrate from TSLint to ESLint and fix linting errors (#589)
|
||||
|
||||
## v1.4.27 - _September 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.26 - _September 12, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.25 - _September 7, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.24 - _September 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.23 - _September 1, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.22 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.21 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.20 - _August 22, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.19 - _August 10, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.18 - _August 9, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.17 - _August 6, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.16 - _July 27, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.15 - _June 14, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -36,9 +36,7 @@ interface ISablier {
|
||||
|
||||
function balanceOf(uint256 streamId, address who) external view returns (uint256 balance);
|
||||
|
||||
function getStream(
|
||||
uint256 streamId
|
||||
)
|
||||
function getStream(uint256 streamId)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
@@ -52,15 +50,11 @@ interface ISablier {
|
||||
uint256 ratePerSecond
|
||||
);
|
||||
|
||||
function createStream(
|
||||
address recipient,
|
||||
uint256 deposit,
|
||||
address tokenAddress,
|
||||
uint256 startTime,
|
||||
uint256 stopTime
|
||||
) external returns (uint256 streamId);
|
||||
function createStream(address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime)
|
||||
external
|
||||
returns (uint256 streamId);
|
||||
|
||||
function withdrawFromStream(uint256 streamId, uint256 funds) external returns (bool);
|
||||
|
||||
function cancelStream(uint256 streamId) external returns (bool);
|
||||
}
|
||||
}
|
@@ -23,6 +23,7 @@ pragma experimental ABIEncoderV2;
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "./IStaking.sol";
|
||||
|
||||
|
||||
contract DefaultPoolOperator {
|
||||
// Immutables
|
||||
IStaking public immutable stakingProxy;
|
||||
@@ -32,7 +33,12 @@ contract DefaultPoolOperator {
|
||||
/// @dev Initializes this contract and creates a staking pool.
|
||||
/// @param stakingProxy_ The 0x staking proxy contract.
|
||||
/// @param weth_ The WETH token contract.
|
||||
constructor(IStaking stakingProxy_, IERC20TokenV06 weth_) public {
|
||||
constructor(
|
||||
IStaking stakingProxy_,
|
||||
IERC20TokenV06 weth_
|
||||
)
|
||||
public
|
||||
{
|
||||
stakingProxy = stakingProxy_;
|
||||
weth = weth_;
|
||||
// operator share = 100%
|
||||
@@ -45,7 +51,9 @@ contract DefaultPoolOperator {
|
||||
/// market making for some reason, thus earning this contract
|
||||
/// some staking rewards. Note that anyone can call this
|
||||
/// function at any time.
|
||||
function returnStakingRewards() external {
|
||||
function returnStakingRewards()
|
||||
external
|
||||
{
|
||||
uint256 wethBalance = weth.balanceOf(address(this));
|
||||
weth.transfer(address(stakingProxy), wethBalance);
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
interface IStaking {
|
||||
/// @dev Statuses that stake can exist in.
|
||||
/// Any stake can be (re)delegated effective at the next epoch
|
||||
@@ -54,28 +55,45 @@ interface IStaking {
|
||||
/// @param operatorShare Portion of rewards owned by the operator, in ppm.
|
||||
/// @param addOperatorAsMaker Adds operator to the created pool as a maker for convenience iff true.
|
||||
/// @return poolId The unique pool id generated for this pool.
|
||||
function createStakingPool(uint32 operatorShare, bool addOperatorAsMaker) external returns (bytes32 poolId);
|
||||
function createStakingPool(uint32 operatorShare, bool addOperatorAsMaker)
|
||||
external
|
||||
returns (bytes32 poolId);
|
||||
|
||||
/// @dev Returns the current staking epoch number.
|
||||
/// @return epoch The current epoch.
|
||||
function currentEpoch() external view returns (uint256 epoch);
|
||||
function currentEpoch()
|
||||
external
|
||||
view
|
||||
returns (uint256 epoch);
|
||||
|
||||
/// @dev Returns the time (in seconds) at which the current staking epoch started.
|
||||
/// @return startTime The start time of the current epoch, in seconds.
|
||||
function currentEpochStartTimeInSeconds() external view returns (uint256 startTime);
|
||||
function currentEpochStartTimeInSeconds()
|
||||
external
|
||||
view
|
||||
returns (uint256 startTime);
|
||||
|
||||
/// @dev Returns the duration of an epoch in seconds. This value can be updated.
|
||||
/// @return duration The duration of an epoch, in seconds.
|
||||
function epochDurationInSeconds() external view returns (uint256 duration);
|
||||
function epochDurationInSeconds()
|
||||
external
|
||||
view
|
||||
returns (uint256 duration);
|
||||
|
||||
/// @dev Returns a staking pool
|
||||
/// @param poolId Unique id of pool.
|
||||
function getStakingPool(bytes32 poolId) external view returns (Pool memory);
|
||||
function getStakingPool(bytes32 poolId)
|
||||
external
|
||||
view
|
||||
returns (Pool memory);
|
||||
|
||||
/// @dev Gets global stake for a given status.
|
||||
/// @param stakeStatus UNDELEGATED or DELEGATED
|
||||
/// @return balance Global stake for given status.
|
||||
function getGlobalStakeByStatus(StakeStatus stakeStatus) external view returns (StoredBalance memory balance);
|
||||
function getGlobalStakeByStatus(StakeStatus stakeStatus)
|
||||
external
|
||||
view
|
||||
returns (StoredBalance memory balance);
|
||||
|
||||
/// @dev Gets an owner's stake balances by status.
|
||||
/// @param staker Owner of stake.
|
||||
@@ -84,20 +102,26 @@ interface IStaking {
|
||||
function getOwnerStakeByStatus(
|
||||
address staker,
|
||||
StakeStatus stakeStatus
|
||||
) external view returns (StoredBalance memory balance);
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (StoredBalance memory balance);
|
||||
|
||||
/// @dev Returns the total stake delegated to a specific staking pool,
|
||||
/// across all members.
|
||||
/// @param poolId Unique Id of pool.
|
||||
/// @return balance Total stake delegated to pool.
|
||||
function getTotalStakeDelegatedToPool(bytes32 poolId) external view returns (StoredBalance memory balance);
|
||||
function getTotalStakeDelegatedToPool(bytes32 poolId)
|
||||
external
|
||||
view
|
||||
returns (StoredBalance memory balance);
|
||||
|
||||
/// @dev Returns the stake delegated to a specific staking pool, by a given staker.
|
||||
/// @param staker of stake.
|
||||
/// @param poolId Unique Id of pool.
|
||||
/// @return balance Stake delegated to pool by staker.
|
||||
function getStakeDelegatedToPoolByOwner(
|
||||
address staker,
|
||||
bytes32 poolId
|
||||
) external view returns (StoredBalance memory balance);
|
||||
function getStakeDelegatedToPoolByOwner(address staker, bytes32 poolId)
|
||||
external
|
||||
view
|
||||
returns (StoredBalance memory balance);
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ pragma experimental ABIEncoderV2;
|
||||
import "./DefaultPoolOperator.sol";
|
||||
import "./IStaking.sol";
|
||||
|
||||
|
||||
interface IZrxTreasury {
|
||||
|
||||
struct TreasuryParameters {
|
||||
uint256 votingPeriod;
|
||||
uint256 proposalThreshold;
|
||||
@@ -55,21 +57,45 @@ interface IZrxTreasury {
|
||||
string description
|
||||
);
|
||||
|
||||
event VoteCast(address voter, bytes32[] operatedPoolIds, uint256 proposalId, bool support, uint256 votingPower);
|
||||
event VoteCast(
|
||||
address voter,
|
||||
bytes32[] operatedPoolIds,
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
uint256 votingPower
|
||||
);
|
||||
|
||||
event ProposalExecuted(uint256 proposalId);
|
||||
|
||||
function stakingProxy() external view returns (IStaking);
|
||||
function stakingProxy()
|
||||
external
|
||||
view
|
||||
returns (IStaking);
|
||||
|
||||
function defaultPoolOperator() external view returns (DefaultPoolOperator);
|
||||
function defaultPoolOperator()
|
||||
external
|
||||
view
|
||||
returns (DefaultPoolOperator);
|
||||
|
||||
function defaultPoolId() external view returns (bytes32);
|
||||
function defaultPoolId()
|
||||
external
|
||||
view
|
||||
returns (bytes32);
|
||||
|
||||
function votingPeriod() external view returns (uint256);
|
||||
function votingPeriod()
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
function proposalThreshold() external view returns (uint256);
|
||||
function proposalThreshold()
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
function quorumThreshold() external view returns (uint256);
|
||||
function quorumThreshold()
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Updates the proposal and quorum thresholds to the given
|
||||
/// values. Note that this function is only callable by the
|
||||
@@ -77,7 +103,11 @@ interface IZrxTreasury {
|
||||
/// updated via a successful treasury proposal.
|
||||
/// @param newProposalThreshold The new value for the proposal threshold.
|
||||
/// @param newQuorumThreshold The new value for the quorum threshold.
|
||||
function updateThresholds(uint256 newProposalThreshold, uint256 newQuorumThreshold) external;
|
||||
function updateThresholds(
|
||||
uint256 newProposalThreshold,
|
||||
uint256 newQuorumThreshold
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Creates a proposal to send ZRX from this treasury on the
|
||||
/// the given actions. Must have at least `proposalThreshold`
|
||||
@@ -101,7 +131,9 @@ interface IZrxTreasury {
|
||||
uint256 executionEpoch,
|
||||
string calldata description,
|
||||
bytes32[] calldata operatedPoolIds
|
||||
) external returns (uint256 proposalId);
|
||||
)
|
||||
external
|
||||
returns (uint256 proposalId);
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
/// during the voting period for that proposal.
|
||||
@@ -112,7 +144,12 @@ interface IZrxTreasury {
|
||||
/// @param operatedPoolIds The pools operated by `msg.sender`. The
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
function castVote(uint256 proposalId, bool support, bytes32[] calldata operatedPoolIds) external;
|
||||
function castVote(
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] calldata operatedPoolIds
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Casts a vote for the given proposal, by signature.
|
||||
/// Only callable during the voting period for that proposal.
|
||||
@@ -133,17 +170,23 @@ interface IZrxTreasury {
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external;
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Executes a proposal that has passed and is
|
||||
/// currently executable.
|
||||
/// @param proposalId The ID of the proposal to execute.
|
||||
/// @param actions Actions associated with the proposal to execute.
|
||||
function execute(uint256 proposalId, ProposedAction[] memory actions) external payable;
|
||||
function execute(uint256 proposalId, ProposedAction[] memory actions)
|
||||
external
|
||||
payable;
|
||||
|
||||
/// @dev Returns the total number of proposals.
|
||||
/// @return count The number of proposals.
|
||||
function proposalCount() external view returns (uint256 count);
|
||||
function proposalCount()
|
||||
external
|
||||
view
|
||||
returns (uint256 count);
|
||||
|
||||
/// @dev Computes the current voting power of the given account.
|
||||
/// Voting power is equal to:
|
||||
@@ -155,8 +198,8 @@ interface IZrxTreasury {
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
/// @return votingPower The current voting power of the given account.
|
||||
function getVotingPower(
|
||||
address account,
|
||||
bytes32[] calldata operatedPoolIds
|
||||
) external view returns (uint256 votingPower);
|
||||
function getVotingPower(address account, bytes32[] calldata operatedPoolIds)
|
||||
external
|
||||
view
|
||||
returns (uint256 votingPower);
|
||||
}
|
||||
|
@@ -26,7 +26,10 @@ import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||
import "@0x/contracts-zero-ex/contracts/src/features/libs/LibSignature.sol";
|
||||
import "./IZrxTreasury.sol";
|
||||
|
||||
contract ZrxTreasury is IZrxTreasury {
|
||||
|
||||
contract ZrxTreasury is
|
||||
IZrxTreasury
|
||||
{
|
||||
using LibSafeMathV06 for uint256;
|
||||
using LibRichErrorsV06 for bytes;
|
||||
using LibBytesV06 for bytes;
|
||||
@@ -38,12 +41,10 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
string private constant CONTRACT_VERSION = "1.0.0";
|
||||
|
||||
/// The EIP-712 typehash for the contract's domain
|
||||
bytes32 private constant DOMAIN_TYPEHASH =
|
||||
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
||||
bytes32 private constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
||||
|
||||
/// The EIP-712 typehash for the vote struct
|
||||
bytes32 private constant VOTE_TYPEHASH =
|
||||
keccak256("TreasuryVote(uint256 proposalId,bool support,bytes32[] operatedPoolIds)");
|
||||
bytes32 private constant VOTE_TYPEHASH = keccak256("TreasuryVote(uint256 proposalId,bool support,bytes32[] operatedPoolIds)");
|
||||
|
||||
// Immutables
|
||||
IStaking public immutable override stakingProxy;
|
||||
@@ -57,14 +58,22 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
|
||||
// Storage
|
||||
Proposal[] public proposals;
|
||||
mapping(uint256 => mapping(address => bool)) public hasVoted;
|
||||
mapping (uint256 => mapping (address => bool)) public hasVoted;
|
||||
|
||||
/// @dev Initializes the ZRX treasury and creates the default
|
||||
/// staking pool.
|
||||
/// @param stakingProxy_ The 0x staking proxy contract.
|
||||
/// @param params Immutable treasury parameters.
|
||||
constructor(IStaking stakingProxy_, TreasuryParameters memory params) public {
|
||||
require(params.votingPeriod < stakingProxy_.epochDurationInSeconds(), "VOTING_PERIOD_TOO_LONG");
|
||||
constructor(
|
||||
IStaking stakingProxy_,
|
||||
TreasuryParameters memory params
|
||||
)
|
||||
public
|
||||
{
|
||||
require(
|
||||
params.votingPeriod < stakingProxy_.epochDurationInSeconds(),
|
||||
"VOTING_PERIOD_TOO_LONG"
|
||||
);
|
||||
stakingProxy = stakingProxy_;
|
||||
votingPeriod = params.votingPeriod;
|
||||
proposalThreshold = params.proposalThreshold;
|
||||
@@ -83,8 +92,10 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
);
|
||||
}
|
||||
|
||||
// solhint-disable
|
||||
/// @dev Allows this contract to receive ether.
|
||||
receive() external payable {}
|
||||
// solhint-enable
|
||||
|
||||
/// @dev Updates the proposal and quorum thresholds to the given
|
||||
/// values. Note that this function is only callable by the
|
||||
@@ -92,7 +103,13 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// updated via a successful treasury proposal.
|
||||
/// @param newProposalThreshold The new value for the proposal threshold.
|
||||
/// @param newQuorumThreshold The new value for the quorum threshold.
|
||||
function updateThresholds(uint256 newProposalThreshold, uint256 newQuorumThreshold) external override {
|
||||
function updateThresholds(
|
||||
uint256 newProposalThreshold,
|
||||
uint256 newQuorumThreshold
|
||||
)
|
||||
external
|
||||
override
|
||||
{
|
||||
require(msg.sender == address(this), "updateThresholds/ONLY_SELF");
|
||||
proposalThreshold = newProposalThreshold;
|
||||
quorumThreshold = newQuorumThreshold;
|
||||
@@ -120,11 +137,24 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
uint256 executionEpoch,
|
||||
string memory description,
|
||||
bytes32[] memory operatedPoolIds
|
||||
) public override returns (uint256 proposalId) {
|
||||
require(getVotingPower(msg.sender, operatedPoolIds) >= proposalThreshold, "propose/INSUFFICIENT_VOTING_POWER");
|
||||
require(actions.length > 0, "propose/NO_ACTIONS_PROPOSED");
|
||||
)
|
||||
public
|
||||
override
|
||||
returns (uint256 proposalId)
|
||||
{
|
||||
require(
|
||||
getVotingPower(msg.sender, operatedPoolIds) >= proposalThreshold,
|
||||
"propose/INSUFFICIENT_VOTING_POWER"
|
||||
);
|
||||
require(
|
||||
actions.length > 0,
|
||||
"propose/NO_ACTIONS_PROPOSED"
|
||||
);
|
||||
uint256 currentEpoch = stakingProxy.currentEpoch();
|
||||
require(executionEpoch >= currentEpoch + 2, "propose/INVALID_EXECUTION_EPOCH");
|
||||
require(
|
||||
executionEpoch >= currentEpoch + 2,
|
||||
"propose/INVALID_EXECUTION_EPOCH"
|
||||
);
|
||||
|
||||
proposalId = proposalCount();
|
||||
Proposal storage newProposal = proposals.push();
|
||||
@@ -132,7 +162,14 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
newProposal.executionEpoch = executionEpoch;
|
||||
newProposal.voteEpoch = currentEpoch + 2;
|
||||
|
||||
emit ProposalCreated(msg.sender, operatedPoolIds, proposalId, actions, executionEpoch, description);
|
||||
emit ProposalCreated(
|
||||
msg.sender,
|
||||
operatedPoolIds,
|
||||
proposalId,
|
||||
actions,
|
||||
executionEpoch,
|
||||
description
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
@@ -144,7 +181,14 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// @param operatedPoolIds The pools operated by `msg.sender`. The
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
function castVote(uint256 proposalId, bool support, bytes32[] memory operatedPoolIds) public override {
|
||||
function castVote(
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] memory operatedPoolIds
|
||||
)
|
||||
public
|
||||
override
|
||||
{
|
||||
return _castVote(msg.sender, proposalId, support, operatedPoolIds);
|
||||
}
|
||||
|
||||
@@ -167,7 +211,10 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) public override {
|
||||
)
|
||||
public
|
||||
override
|
||||
{
|
||||
bytes32 structHash = keccak256(
|
||||
abi.encode(VOTE_TYPEHASH, proposalId, support, keccak256(abi.encodePacked(operatedPoolIds)))
|
||||
);
|
||||
@@ -181,7 +228,11 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// currently executable.
|
||||
/// @param proposalId The ID of the proposal to execute.
|
||||
/// @param actions Actions associated with the proposal to execute.
|
||||
function execute(uint256 proposalId, ProposedAction[] memory actions) public payable override {
|
||||
function execute(uint256 proposalId, ProposedAction[] memory actions)
|
||||
public
|
||||
payable
|
||||
override
|
||||
{
|
||||
if (proposalId >= proposalCount()) {
|
||||
revert("execute/INVALID_PROPOSAL_ID");
|
||||
}
|
||||
@@ -193,7 +244,10 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
for (uint256 i = 0; i != actions.length; i++) {
|
||||
ProposedAction memory action = actions[i];
|
||||
(bool didSucceed, ) = action.target.call{value: action.value}(action.data);
|
||||
require(didSucceed, "execute/ACTION_EXECUTION_FAILED");
|
||||
require(
|
||||
didSucceed,
|
||||
"execute/ACTION_EXECUTION_FAILED"
|
||||
);
|
||||
}
|
||||
|
||||
emit ProposalExecuted(proposalId);
|
||||
@@ -201,7 +255,12 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
|
||||
/// @dev Returns the total number of proposals.
|
||||
/// @return count The number of proposals.
|
||||
function proposalCount() public view override returns (uint256 count) {
|
||||
function proposalCount()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint256 count)
|
||||
{
|
||||
return proposals.length;
|
||||
}
|
||||
|
||||
@@ -215,29 +274,41 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
/// @return votingPower The current voting power of the given account.
|
||||
function getVotingPower(
|
||||
address account,
|
||||
bytes32[] memory operatedPoolIds
|
||||
) public view override returns (uint256 votingPower) {
|
||||
uint256 delegatedBalance = stakingProxy
|
||||
.getOwnerStakeByStatus(account, IStaking.StakeStatus.DELEGATED)
|
||||
.currentEpochBalance;
|
||||
uint256 balanceDelegatedToDefaultPool = stakingProxy
|
||||
.getStakeDelegatedToPoolByOwner(account, defaultPoolId)
|
||||
.currentEpochBalance;
|
||||
function getVotingPower(address account, bytes32[] memory operatedPoolIds)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint256 votingPower)
|
||||
{
|
||||
uint256 delegatedBalance = stakingProxy.getOwnerStakeByStatus(
|
||||
account,
|
||||
IStaking.StakeStatus.DELEGATED
|
||||
).currentEpochBalance;
|
||||
uint256 balanceDelegatedToDefaultPool = stakingProxy.getStakeDelegatedToPoolByOwner(
|
||||
account,
|
||||
defaultPoolId
|
||||
).currentEpochBalance;
|
||||
|
||||
// Voting power for ZRX delegated to the default pool is not diluted,
|
||||
// so we double-count the balance delegated to the default pool before
|
||||
// dividing by 2.
|
||||
votingPower = delegatedBalance.safeAdd(balanceDelegatedToDefaultPool).safeDiv(2);
|
||||
votingPower = delegatedBalance
|
||||
.safeAdd(balanceDelegatedToDefaultPool)
|
||||
.safeDiv(2);
|
||||
|
||||
// Add voting power for operated staking pools.
|
||||
for (uint256 i = 0; i != operatedPoolIds.length; i++) {
|
||||
for (uint256 j = 0; j != i; j++) {
|
||||
require(operatedPoolIds[i] != operatedPoolIds[j], "getVotingPower/DUPLICATE_POOL_ID");
|
||||
require(
|
||||
operatedPoolIds[i] != operatedPoolIds[j],
|
||||
"getVotingPower/DUPLICATE_POOL_ID"
|
||||
);
|
||||
}
|
||||
IStaking.Pool memory pool = stakingProxy.getStakingPool(operatedPoolIds[i]);
|
||||
require(pool.operator == account, "getVotingPower/POOL_NOT_OPERATED_BY_ACCOUNT");
|
||||
require(
|
||||
pool.operator == account,
|
||||
"getVotingPower/POOL_NOT_OPERATED_BY_ACCOUNT"
|
||||
);
|
||||
uint96 stakeDelegatedToPool = stakingProxy
|
||||
.getTotalStakeDelegatedToPool(operatedPoolIds[i])
|
||||
.currentEpochBalance;
|
||||
@@ -251,10 +322,25 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// @dev Checks whether the given proposal is executable.
|
||||
/// Reverts if not.
|
||||
/// @param proposal The proposal to check.
|
||||
function _assertProposalExecutable(Proposal memory proposal, ProposedAction[] memory actions) private view {
|
||||
require(keccak256(abi.encode(actions)) == proposal.actionsHash, "_assertProposalExecutable/INVALID_ACTIONS");
|
||||
require(_hasProposalPassed(proposal), "_assertProposalExecutable/PROPOSAL_HAS_NOT_PASSED");
|
||||
require(!proposal.executed, "_assertProposalExecutable/PROPOSAL_ALREADY_EXECUTED");
|
||||
function _assertProposalExecutable(
|
||||
Proposal memory proposal,
|
||||
ProposedAction[] memory actions
|
||||
)
|
||||
private
|
||||
view
|
||||
{
|
||||
require(
|
||||
keccak256(abi.encode(actions)) == proposal.actionsHash,
|
||||
"_assertProposalExecutable/INVALID_ACTIONS"
|
||||
);
|
||||
require(
|
||||
_hasProposalPassed(proposal),
|
||||
"_assertProposalExecutable/PROPOSAL_HAS_NOT_PASSED"
|
||||
);
|
||||
require(
|
||||
!proposal.executed,
|
||||
"_assertProposalExecutable/PROPOSAL_ALREADY_EXECUTED"
|
||||
);
|
||||
require(
|
||||
stakingProxy.currentEpoch() == proposal.executionEpoch,
|
||||
"_assertProposalExecutable/CANNOT_EXECUTE_THIS_EPOCH"
|
||||
@@ -264,7 +350,11 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// @dev Checks whether the given proposal has passed or not.
|
||||
/// @param proposal The proposal to check.
|
||||
/// @return hasPassed Whether the proposal has passed.
|
||||
function _hasProposalPassed(Proposal memory proposal) private view returns (bool hasPassed) {
|
||||
function _hasProposalPassed(Proposal memory proposal)
|
||||
private
|
||||
view
|
||||
returns (bool hasPassed)
|
||||
{
|
||||
// Proposal is not passed until the vote is over.
|
||||
if (!_hasVoteEnded(proposal.voteEpoch)) {
|
||||
return false;
|
||||
@@ -284,7 +374,11 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
/// epoch has ended or not.
|
||||
/// @param voteEpoch The epoch at which the vote started.
|
||||
/// @return hasEnded Whether the vote has ended.
|
||||
function _hasVoteEnded(uint256 voteEpoch) private view returns (bool hasEnded) {
|
||||
function _hasVoteEnded(uint256 voteEpoch)
|
||||
private
|
||||
view
|
||||
returns (bool hasEnded)
|
||||
{
|
||||
uint256 currentEpoch = stakingProxy.currentEpoch();
|
||||
if (currentEpoch < voteEpoch) {
|
||||
return false;
|
||||
@@ -294,14 +388,23 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
}
|
||||
// voteEpoch == currentEpoch
|
||||
// Vote ends at currentEpochStartTime + votingPeriod
|
||||
uint256 voteEndTime = stakingProxy.currentEpochStartTimeInSeconds().safeAdd(votingPeriod);
|
||||
uint256 voteEndTime = stakingProxy
|
||||
.currentEpochStartTimeInSeconds()
|
||||
.safeAdd(votingPeriod);
|
||||
return block.timestamp > voteEndTime;
|
||||
}
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
/// during the voting period for that proposal. See
|
||||
/// `getVotingPower` for how voting power is computed.
|
||||
function _castVote(address voter, uint256 proposalId, bool support, bytes32[] memory operatedPoolIds) private {
|
||||
function _castVote(
|
||||
address voter,
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] memory operatedPoolIds
|
||||
)
|
||||
private
|
||||
{
|
||||
if (proposalId >= proposalCount()) {
|
||||
revert("_castVote/INVALID_PROPOSAL_ID");
|
||||
}
|
||||
@@ -310,7 +413,10 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
}
|
||||
|
||||
Proposal memory proposal = proposals[proposalId];
|
||||
if (proposal.voteEpoch != stakingProxy.currentEpoch() || _hasVoteEnded(proposal.voteEpoch)) {
|
||||
if (
|
||||
proposal.voteEpoch != stakingProxy.currentEpoch() ||
|
||||
_hasVoteEnded(proposal.voteEpoch)
|
||||
) {
|
||||
revert("_castVote/VOTING_IS_CLOSED");
|
||||
}
|
||||
|
||||
@@ -320,21 +426,27 @@ contract ZrxTreasury is IZrxTreasury {
|
||||
}
|
||||
|
||||
if (support) {
|
||||
proposals[proposalId].votesFor = proposals[proposalId].votesFor.safeAdd(votingPower);
|
||||
proposals[proposalId].votesFor = proposals[proposalId].votesFor
|
||||
.safeAdd(votingPower);
|
||||
} else {
|
||||
proposals[proposalId].votesAgainst = proposals[proposalId].votesAgainst.safeAdd(votingPower);
|
||||
proposals[proposalId].votesAgainst = proposals[proposalId].votesAgainst
|
||||
.safeAdd(votingPower);
|
||||
}
|
||||
hasVoted[proposalId][voter] = true;
|
||||
|
||||
emit VoteCast(voter, operatedPoolIds, proposalId, support, votingPower);
|
||||
emit VoteCast(
|
||||
voter,
|
||||
operatedPoolIds,
|
||||
proposalId,
|
||||
support,
|
||||
votingPower
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the Ethereum chain id
|
||||
function _getChainId() private pure returns (uint256) {
|
||||
uint256 chainId;
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
assembly { chainId := chainid() }
|
||||
return chainId;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-treasury",
|
||||
"version": "1.4.36",
|
||||
"version": "1.4.15",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -21,11 +21,12 @@
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
|
||||
"lint": "eslint src test",
|
||||
"fix": "eslint --fix src test",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"test:circleci": "yarn test",
|
||||
"contracts:gen": "contracts-gen generate",
|
||||
"contracts:copy": "contracts-gen copy",
|
||||
"lint-contracts": "#solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
|
||||
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||
"publish:private": "yarn build && gitpkg publish"
|
||||
@@ -45,41 +46,40 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.8.1",
|
||||
"@0x/contract-addresses": "^7.4.1",
|
||||
"@0x/abi-gen": "^5.8.0",
|
||||
"@0x/contract-addresses": "^6.16.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.19",
|
||||
"@0x/contracts-erc20": "^3.3.53",
|
||||
"@0x/contracts-gen": "^2.0.48",
|
||||
"@0x/contracts-erc20": "^3.3.32",
|
||||
"@0x/contracts-gen": "^2.0.46",
|
||||
"@0x/contracts-staking": "^2.0.45",
|
||||
"@0x/contracts-test-utils": "^5.4.43",
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
"@0x/contracts-test-utils": "^5.4.23",
|
||||
"@0x/sol-compiler": "^4.8.1",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@types/isomorphic-fetch": "^0.0.35",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/prompts": "^2.0.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||
"@typescript-eslint/parser": "^5.38.0",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"prompts": "^2.4.0",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "~0.16.11",
|
||||
"typescript": "4.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/protocol-utils": "^11.17.2",
|
||||
"@0x/subproviders": "^7.0.0",
|
||||
"@0x/base-contract": "^6.5.0",
|
||||
"@0x/protocol-utils": "^11.15.0",
|
||||
"@0x/subproviders": "^6.6.5",
|
||||
"@0x/types": "^3.3.6",
|
||||
"@0x/typescript-typings": "^5.3.1",
|
||||
"@0x/utils": "^7.0.0",
|
||||
"@0x/web3-wrapper": "^8.0.0",
|
||||
"ethereum-types": "^3.7.1",
|
||||
"@0x/utils": "^6.5.3",
|
||||
"@0x/web3-wrapper": "^7.6.5",
|
||||
"ethereum-types": "^3.7.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
13
contracts/treasury/tslint.json
Normal file
13
contracts/treasury/tslint.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false,
|
||||
"max-file-line-count": false,
|
||||
"no-non-null-assertion": false,
|
||||
"no-unnecessary-type-assertion": false,
|
||||
"number-literal-format": false
|
||||
},
|
||||
"linterOptions": {
|
||||
"exclude": ["src/artifacts.ts", "test/artifacts.ts"]
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
||||
"overrides": [],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"ignorePatterns": [
|
||||
"lib/**/*",
|
||||
"contracts/**/*",
|
||||
"generated-wrappers/**/*",
|
||||
"generated-artifacts/**/*",
|
||||
"test/generated-wrappers/**/*",
|
||||
"test/generated-artifacts/**/*"
|
||||
|
||||
],
|
||||
"rules": {}
|
||||
}
|
@@ -1,194 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1669235113,
|
||||
"version": "4.8.34",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1668477029,
|
||||
"version": "4.8.33",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667607537,
|
||||
"version": "4.8.32",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1667427402,
|
||||
"version": "4.8.31",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666645023,
|
||||
"version": "4.8.30",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1666381417,
|
||||
"version": "4.8.29",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665670315,
|
||||
"version": "4.8.28",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1665531940,
|
||||
"version": "4.8.27",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.8.26",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Migrate from TSLint to ESLint and fix linting errors",
|
||||
"pr": 589
|
||||
}
|
||||
],
|
||||
"timestamp": 1665013355
|
||||
},
|
||||
{
|
||||
"timestamp": 1663786955,
|
||||
"version": "4.8.25",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662998180,
|
||||
"version": "4.8.24",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662559804,
|
||||
"version": "4.8.23",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662147076,
|
||||
"version": "4.8.22",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1662046042,
|
||||
"version": "4.8.21",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661462289,
|
||||
"version": "4.8.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661459661,
|
||||
"version": "4.8.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1661145612,
|
||||
"version": "4.8.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660093941,
|
||||
"version": "4.8.17",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1660073235,
|
||||
"version": "4.8.16",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1659750766,
|
||||
"version": "4.8.15",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1658950329,
|
||||
"version": "4.8.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1655244958,
|
||||
"version": "4.8.13",
|
||||
|
@@ -5,90 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.8.34 - _November 23, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.33 - _November 15, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.32 - _November 5, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.31 - _November 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.30 - _October 24, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.29 - _October 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.28 - _October 13, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.27 - _October 11, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.26 - _October 5, 2022_
|
||||
|
||||
* Migrate from TSLint to ESLint and fix linting errors (#589)
|
||||
|
||||
## v4.8.25 - _September 21, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.24 - _September 12, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.23 - _September 7, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.22 - _September 2, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.21 - _September 1, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.20 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.19 - _August 25, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.18 - _August 22, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.17 - _August 10, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.16 - _August 9, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.15 - _August 6, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.14 - _July 27, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.13 - _June 14, 2022_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -63,3 +63,7 @@ yarn lint
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
||||
|
@@ -23,9 +23,14 @@ import "./LibAuthorizableRichErrors.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
import "./Ownable.sol";
|
||||
|
||||
contract Authorizable is Ownable, IAuthorizable {
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract Authorizable is
|
||||
Ownable,
|
||||
IAuthorizable
|
||||
{
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized() {
|
||||
modifier onlyAuthorized {
|
||||
_assertSenderIsAuthorized();
|
||||
_;
|
||||
}
|
||||
@@ -33,24 +38,33 @@ contract Authorizable is Ownable, IAuthorizable {
|
||||
/// @dev Whether an adderss is authorized to call privileged functions.
|
||||
/// @param 0 Address to query.
|
||||
/// @return 0 Whether the address is authorized.
|
||||
mapping(address => bool) public authorized;
|
||||
mapping (address => bool) public authorized;
|
||||
/// @dev Whether an adderss is authorized to call privileged functions.
|
||||
/// @param 0 Index of authorized address.
|
||||
/// @return 0 Authorized address.
|
||||
address[] public authorities;
|
||||
|
||||
/// @dev Initializes the `owner` address.
|
||||
constructor() public Ownable() {}
|
||||
constructor()
|
||||
public
|
||||
Ownable()
|
||||
{}
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target) external onlyOwner {
|
||||
function addAuthorizedAddress(address target)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
_addAuthorizedAddress(target);
|
||||
}
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target) external onlyOwner {
|
||||
function removeAuthorizedAddress(address target)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
if (!authorized[target]) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.TargetNotAuthorizedError(target));
|
||||
}
|
||||
@@ -65,18 +79,31 @@ contract Authorizable is Ownable, IAuthorizable {
|
||||
/// @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 onlyOwner {
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
_removeAuthorizedAddressAtIndex(target, index);
|
||||
}
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses() external view returns (address[] memory) {
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
return authorities;
|
||||
}
|
||||
|
||||
/// @dev Reverts if msg.sender is not authorized.
|
||||
function _assertSenderIsAuthorized() internal view {
|
||||
function _assertSenderIsAuthorized()
|
||||
internal
|
||||
view
|
||||
{
|
||||
if (!authorized[msg.sender]) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.SenderNotAuthorizedError(msg.sender));
|
||||
}
|
||||
@@ -84,7 +111,9 @@ contract Authorizable is Ownable, IAuthorizable {
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function _addAuthorizedAddress(address target) internal {
|
||||
function _addAuthorizedAddress(address target)
|
||||
internal
|
||||
{
|
||||
// Ensure that the target is not the zero address.
|
||||
if (target == address(0)) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.ZeroCantBeAuthorizedError());
|
||||
@@ -103,15 +132,26 @@ contract Authorizable is Ownable, IAuthorizable {
|
||||
/// @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) internal {
|
||||
function _removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
{
|
||||
if (!authorized[target]) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.TargetNotAuthorizedError(target));
|
||||
}
|
||||
if (index >= authorities.length) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.IndexOutOfBoundsError(index, authorities.length));
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.IndexOutOfBoundsError(
|
||||
index,
|
||||
authorities.length
|
||||
));
|
||||
}
|
||||
if (authorities[index] != target) {
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.AuthorizedAddressMismatchError(authorities[index], target));
|
||||
LibRichErrors.rrevert(LibAuthorizableRichErrors.AuthorizedAddressMismatchError(
|
||||
authorities[index],
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
delete authorized[target];
|
||||
|
@@ -18,124 +18,201 @@
|
||||
|
||||
pragma solidity ^0.5.16;
|
||||
|
||||
|
||||
/// @dev A library for working with 18 digit, base 10 decimals.
|
||||
library D18 {
|
||||
|
||||
/// @dev Decimal places for dydx value quantities.
|
||||
uint256 private constant PRECISION = 18;
|
||||
/// @dev 1.0 in base-18 decimal.
|
||||
int256 private constant DECIMAL_ONE = int256(10 ** PRECISION);
|
||||
/// @dev Minimum signed integer value.
|
||||
int256 private constant MIN_INT256_VALUE =
|
||||
int256(0x8000000000000000000000000000000000000000000000000000000000000000);
|
||||
int256 private constant MIN_INT256_VALUE = int256(0x8000000000000000000000000000000000000000000000000000000000000000);
|
||||
|
||||
/// @dev Return `1.0`
|
||||
function one() internal pure returns (int256 r) {
|
||||
function one()
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = DECIMAL_ONE;
|
||||
}
|
||||
|
||||
/// @dev Add two decimals.
|
||||
function add(int256 a, int256 b) internal pure returns (int256 r) {
|
||||
function add(int256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = _add(a, b);
|
||||
}
|
||||
|
||||
/// @dev Add two decimals.
|
||||
function add(uint256 a, int256 b) internal pure returns (int256 r) {
|
||||
function add(uint256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _add(int256(a), b);
|
||||
}
|
||||
|
||||
/// @dev Add two decimals.
|
||||
function add(int256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function add(int256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _add(a, int256(b));
|
||||
}
|
||||
|
||||
/// @dev Add two decimals.
|
||||
function add(uint256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function add(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _add(int256(a), int256(b));
|
||||
}
|
||||
|
||||
/// @dev Subract two decimals.
|
||||
function sub(int256 a, int256 b) internal pure returns (int256 r) {
|
||||
function sub(int256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = _add(a, -b);
|
||||
}
|
||||
|
||||
/// @dev Subract two decimals.
|
||||
function sub(uint256 a, int256 b) internal pure returns (int256 r) {
|
||||
function sub(uint256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _add(int256(a), -b);
|
||||
}
|
||||
|
||||
/// @dev Subract two decimals.
|
||||
function sub(uint256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function sub(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _add(int256(a), -int256(b));
|
||||
}
|
||||
|
||||
/// @dev Multiply two decimals.
|
||||
function mul(int256 a, int256 b) internal pure returns (int256 r) {
|
||||
function mul(int256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = _div(_mul(a, b), DECIMAL_ONE);
|
||||
}
|
||||
|
||||
/// @dev Multiply two decimals.
|
||||
function mul(uint256 a, int256 b) internal pure returns (int256 r) {
|
||||
function mul(uint256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(int256(a), b), DECIMAL_ONE);
|
||||
}
|
||||
|
||||
/// @dev Multiply two decimals.
|
||||
function mul(int256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function mul(int256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(a, int256(b)), DECIMAL_ONE);
|
||||
}
|
||||
|
||||
/// @dev Multiply two decimals.
|
||||
function mul(uint256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function mul(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(int256(a), int256(b)), DECIMAL_ONE);
|
||||
}
|
||||
|
||||
/// @dev Divide two decimals.
|
||||
function div(int256 a, int256 b) internal pure returns (int256 r) {
|
||||
function div(int256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = _div(_mul(a, DECIMAL_ONE), b);
|
||||
}
|
||||
|
||||
/// @dev Divide two decimals.
|
||||
function div(uint256 a, int256 b) internal pure returns (int256 r) {
|
||||
function div(uint256 a, int256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(int256(a), DECIMAL_ONE), b);
|
||||
}
|
||||
|
||||
/// @dev Divide two decimals.
|
||||
function div(int256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function div(int256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(a, DECIMAL_ONE), int256(b));
|
||||
}
|
||||
|
||||
/// @dev Divide two decimals.
|
||||
function div(uint256 a, uint256 b) internal pure returns (int256 r) {
|
||||
function div(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(int256(a), DECIMAL_ONE), int256(b));
|
||||
}
|
||||
|
||||
/// @dev Safely convert an unsigned integer into a signed integer.
|
||||
function toSigned(uint256 a) internal pure returns (int256 r) {
|
||||
function toSigned(uint256 a)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = int256(a);
|
||||
}
|
||||
|
||||
/// @dev Clip a signed value to be positive.
|
||||
function clip(int256 a) internal pure returns (int256 r) {
|
||||
function clip(int256 a)
|
||||
internal
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = a < 0 ? 0 : a;
|
||||
}
|
||||
|
||||
/// @dev Safely multiply two signed integers.
|
||||
function _mul(int256 a, int256 b) private pure returns (int256 r) {
|
||||
function _mul(int256 a, int256 b)
|
||||
private
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
if (a == 0 || b == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -145,15 +222,27 @@ library D18 {
|
||||
}
|
||||
|
||||
/// @dev Safely divide two signed integers.
|
||||
function _div(int256 a, int256 b) private pure returns (int256 r) {
|
||||
function _div(int256 a, int256 b)
|
||||
private
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(b != 0, "D18/DECIMAL_DIV_BY_ZERO");
|
||||
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_DIV_OVERFLOW");
|
||||
r = a / b;
|
||||
}
|
||||
|
||||
/// @dev Safely add two signed integers.
|
||||
function _add(int256 a, int256 b) private pure returns (int256 r) {
|
||||
function _add(int256 a, int256 b)
|
||||
private
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
r = a + b;
|
||||
require(!((a < 0 && b < 0 && r > a) || (a > 0 && b > 0 && r < a)), "D18/DECIMAL_ADD_OVERFLOW");
|
||||
require(
|
||||
!((a < 0 && b < 0 && r > a) || (a > 0 && b > 0 && r < a)),
|
||||
"D18/DECIMAL_ADD_OVERFLOW"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,234 +18,306 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract DeploymentConstants {
|
||||
|
||||
// solhint-disable separate-by-one-line-in-contract
|
||||
|
||||
// Mainnet addresses ///////////////////////////////////////////////////////
|
||||
/// @dev Mainnet address of the WETH contract.
|
||||
address private constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
||||
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
||||
/// @dev Mainnet address of the KyberNetworkProxy contract.
|
||||
address private constant KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
|
||||
address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
|
||||
/// @dev Mainnet address of the KyberHintHandler contract.
|
||||
address private constant KYBER_HINT_HANDLER_ADDRESS = 0xa1C0Fa73c39CFBcC11ec9Eb1Afc665aba9996E2C;
|
||||
address constant private KYBER_HINT_HANDLER_ADDRESS = 0xa1C0Fa73c39CFBcC11ec9Eb1Afc665aba9996E2C;
|
||||
/// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
||||
address private constant UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
|
||||
address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
|
||||
/// @dev Mainnet address of the `UniswapV2Router01` contract.
|
||||
address private constant UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
||||
address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
||||
/// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
||||
address private constant ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D;
|
||||
address constant private ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D;
|
||||
/// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
||||
address private constant ERC20_BRIDGE_PROXY_ADDRESS = 0x8ED95d1746bf1E4dAb58d8ED4724f1Ef95B20Db0;
|
||||
address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x8ED95d1746bf1E4dAb58d8ED4724f1Ef95B20Db0;
|
||||
///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
||||
address private constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
||||
address constant private DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
||||
/// @dev Mainnet address of the `Chai` contract
|
||||
address private constant CHAI_ADDRESS = 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215;
|
||||
address constant private CHAI_ADDRESS = 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215;
|
||||
/// @dev Mainnet address of the 0x DevUtils contract.
|
||||
address private constant DEV_UTILS_ADDRESS = 0x74134CF88b21383713E096a5ecF59e297dc7f547;
|
||||
address constant private DEV_UTILS_ADDRESS = 0x74134CF88b21383713E096a5ecF59e297dc7f547;
|
||||
/// @dev Kyber ETH pseudo-address.
|
||||
address internal constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
/// @dev Mainnet address of the dYdX contract.
|
||||
address private constant DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
||||
address constant private DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
||||
/// @dev Mainnet address of the GST2 contract
|
||||
address private constant GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
|
||||
address constant private GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
|
||||
/// @dev Mainnet address of the GST Collector
|
||||
address private constant GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
|
||||
address constant private GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
|
||||
/// @dev Mainnet address of the mStable mUSD contract.
|
||||
address private constant MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
|
||||
address constant private MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
|
||||
/// @dev Mainnet address of the Mooniswap Registry contract
|
||||
address private constant MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
|
||||
address constant private MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
|
||||
/// @dev Mainnet address of the DODO Registry (ZOO) contract
|
||||
address private constant DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
||||
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
||||
/// @dev Mainnet address of the DODO Helper contract
|
||||
address private constant DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
|
||||
address constant private DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
|
||||
|
||||
// // Ropsten addresses ///////////////////////////////////////////////////////
|
||||
/// @dev Mainnet address of the WETH contract.
|
||||
// /// @dev Mainnet address of the WETH contract.
|
||||
// address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
|
||||
/// @dev Mainnet address of the KyberNetworkProxy contract.
|
||||
// /// @dev Mainnet address of the KyberNetworkProxy contract.
|
||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0xd719c34261e099Fdb33030ac8909d5788D3039C4;
|
||||
/// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
||||
// /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0x9c83dCE8CA20E9aAF9D3efc003b2ea62aBC08351;
|
||||
/// @dev Mainnet address of the `UniswapV2Router01` contract.
|
||||
// /// @dev Mainnet address of the `UniswapV2Router01` contract.
|
||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
||||
/// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
||||
// /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
||||
// address constant private ETH2DAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
||||
// /// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xb344afeD348de15eb4a9e180205A2B0739628339;
|
||||
// ///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
||||
// address constant private DAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the `Chai` contract
|
||||
// /// @dev Mainnet address of the `Chai` contract
|
||||
// address constant private CHAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the 0x DevUtils contract.
|
||||
// /// @dev Mainnet address of the 0x DevUtils contract.
|
||||
// address constant private DEV_UTILS_ADDRESS = 0xC812AF3f3fBC62F76ea4262576EC0f49dB8B7f1c;
|
||||
/// @dev Kyber ETH pseudo-address.
|
||||
// /// @dev Kyber ETH pseudo-address.
|
||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
/// @dev Mainnet address of the dYdX contract.
|
||||
// /// @dev Mainnet address of the dYdX contract.
|
||||
// address constant private DYDX_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the GST2 contract
|
||||
// /// @dev Mainnet address of the GST2 contract
|
||||
// address constant private GST_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the GST Collector
|
||||
// /// @dev Mainnet address of the GST Collector
|
||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the mStable mUSD contract.
|
||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
||||
// address constant private MUSD_ADDRESS = 0x4E1000616990D83e56f4b5fC6CC8602DcfD20459;
|
||||
|
||||
// // Rinkeby addresses ///////////////////////////////////////////////////////
|
||||
/// @dev Mainnet address of the WETH contract.
|
||||
// /// @dev Mainnet address of the WETH contract.
|
||||
// address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
|
||||
/// @dev Mainnet address of the KyberNetworkProxy contract.
|
||||
// /// @dev Mainnet address of the KyberNetworkProxy contract.
|
||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x0d5371e5EE23dec7DF251A8957279629aa79E9C5;
|
||||
/// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
||||
// /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36;
|
||||
/// @dev Mainnet address of the `UniswapV2Router01` contract.
|
||||
// /// @dev Mainnet address of the `UniswapV2Router01` contract.
|
||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
||||
/// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
||||
// /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
||||
// address constant private ETH2DAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
||||
// /// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xA2AA4bEFED748Fba27a3bE7Dfd2C4b2c6DB1F49B;
|
||||
// ///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
||||
// address constant private DAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the `Chai` contract
|
||||
// /// @dev Mainnet address of the `Chai` contract
|
||||
// address constant private CHAI_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the 0x DevUtils contract.
|
||||
// /// @dev Mainnet address of the 0x DevUtils contract.
|
||||
// address constant private DEV_UTILS_ADDRESS = 0x46B5BC959e8A754c0256FFF73bF34A52Ad5CdfA9;
|
||||
/// @dev Kyber ETH pseudo-address.
|
||||
// /// @dev Kyber ETH pseudo-address.
|
||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
/// @dev Mainnet address of the dYdX contract.
|
||||
// /// @dev Mainnet address of the dYdX contract.
|
||||
// address constant private DYDX_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the GST2 contract
|
||||
// /// @dev Mainnet address of the GST2 contract
|
||||
// address constant private GST_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the GST Collector
|
||||
// /// @dev Mainnet address of the GST Collector
|
||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the mStable mUSD contract.
|
||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
||||
// address constant private MUSD_ADDRESS = address(0);
|
||||
|
||||
// // Kovan addresses /////////////////////////////////////////////////////////
|
||||
/// @dev Kovan address of the WETH contract.
|
||||
// /// @dev Kovan address of the WETH contract.
|
||||
// address constant private WETH_ADDRESS = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
|
||||
/// @dev Kovan address of the KyberNetworkProxy contract.
|
||||
// /// @dev Kovan address of the KyberNetworkProxy contract.
|
||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D;
|
||||
/// @dev Kovan address of the `UniswapExchangeFactory` contract.
|
||||
// /// @dev Kovan address of the `UniswapExchangeFactory` contract.
|
||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30;
|
||||
/// @dev Kovan address of the `UniswapV2Router01` contract.
|
||||
// /// @dev Kovan address of the `UniswapV2Router01` contract.
|
||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
||||
/// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
|
||||
// /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
|
||||
// address constant private ETH2DAI_ADDRESS = 0xe325acB9765b02b8b418199bf9650972299235F4;
|
||||
/// @dev Kovan address of the `ERC20BridgeProxy` contract
|
||||
// /// @dev Kovan address of the `ERC20BridgeProxy` contract
|
||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x3577552C1Fb7A44aD76BeEB7aB53251668A21F8D;
|
||||
/// @dev Kovan address of the `Chai` contract
|
||||
// /// @dev Kovan address of the `Chai` contract
|
||||
// address constant private CHAI_ADDRESS = address(0);
|
||||
/// @dev Kovan address of the `Dai` (multi-collateral) contract
|
||||
// /// @dev Kovan address of the `Dai` (multi-collateral) contract
|
||||
// address constant private DAI_ADDRESS = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
|
||||
/// @dev Kovan address of the 0x DevUtils contract.
|
||||
// /// @dev Kovan address of the 0x DevUtils contract.
|
||||
// address constant private DEV_UTILS_ADDRESS = 0x9402639A828BdF4E9e4103ac3B69E1a6E522eB59;
|
||||
/// @dev Kyber ETH pseudo-address.
|
||||
// /// @dev Kyber ETH pseudo-address.
|
||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
/// @dev Kovan address of the dYdX contract.
|
||||
// /// @dev Kovan address of the dYdX contract.
|
||||
// address constant private DYDX_ADDRESS = address(0);
|
||||
/// @dev Kovan address of the GST2 contract
|
||||
// /// @dev Kovan address of the GST2 contract
|
||||
// address constant private GST_ADDRESS = address(0);
|
||||
/// @dev Kovan address of the GST Collector
|
||||
// /// @dev Kovan address of the GST Collector
|
||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
||||
/// @dev Mainnet address of the mStable mUSD contract.
|
||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
||||
// address constant private MUSD_ADDRESS = address(0);
|
||||
|
||||
/// @dev Overridable way to get the `KyberNetworkProxy` address.
|
||||
/// @return kyberAddress The `IKyberNetworkProxy` address.
|
||||
function _getKyberNetworkProxyAddress() internal view returns (address kyberAddress) {
|
||||
function _getKyberNetworkProxyAddress()
|
||||
internal
|
||||
view
|
||||
returns (address kyberAddress)
|
||||
{
|
||||
return KYBER_NETWORK_PROXY_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the `KyberHintHandler` address.
|
||||
/// @return kyberAddress The `IKyberHintHandler` address.
|
||||
function _getKyberHintHandlerAddress() internal view returns (address hintHandlerAddress) {
|
||||
function _getKyberHintHandlerAddress()
|
||||
internal
|
||||
view
|
||||
returns (address hintHandlerAddress)
|
||||
{
|
||||
return KYBER_HINT_HANDLER_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the WETH address.
|
||||
/// @return wethAddress The WETH address.
|
||||
function _getWethAddress() internal view returns (address wethAddress) {
|
||||
function _getWethAddress()
|
||||
internal
|
||||
view
|
||||
returns (address wethAddress)
|
||||
{
|
||||
return WETH_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the `UniswapExchangeFactory` address.
|
||||
/// @return uniswapAddress The `UniswapExchangeFactory` address.
|
||||
function _getUniswapExchangeFactoryAddress() internal view returns (address uniswapAddress) {
|
||||
function _getUniswapExchangeFactoryAddress()
|
||||
internal
|
||||
view
|
||||
returns (address uniswapAddress)
|
||||
{
|
||||
return UNISWAP_EXCHANGE_FACTORY_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the `UniswapV2Router01` address.
|
||||
/// @return uniswapRouterAddress The `UniswapV2Router01` address.
|
||||
function _getUniswapV2Router01Address() internal view returns (address uniswapRouterAddress) {
|
||||
function _getUniswapV2Router01Address()
|
||||
internal
|
||||
view
|
||||
returns (address uniswapRouterAddress)
|
||||
{
|
||||
return UNISWAP_V2_ROUTER_01_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the Eth2Dai `MatchingMarket` contract.
|
||||
/// @return eth2daiAddress The Eth2Dai `MatchingMarket` contract.
|
||||
function _getEth2DaiAddress() internal view returns (address eth2daiAddress) {
|
||||
function _getEth2DaiAddress()
|
||||
internal
|
||||
view
|
||||
returns (address eth2daiAddress)
|
||||
{
|
||||
return ETH2DAI_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the `ERC20BridgeProxy` contract.
|
||||
/// @return erc20BridgeProxyAddress The `ERC20BridgeProxy` contract.
|
||||
function _getERC20BridgeProxyAddress() internal view returns (address erc20BridgeProxyAddress) {
|
||||
function _getERC20BridgeProxyAddress()
|
||||
internal
|
||||
view
|
||||
returns (address erc20BridgeProxyAddress)
|
||||
{
|
||||
return ERC20_BRIDGE_PROXY_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the `Dai` contract.
|
||||
/// @return daiAddress The `Dai` contract.
|
||||
function _getDaiAddress() internal view returns (address daiAddress) {
|
||||
function _getDaiAddress()
|
||||
internal
|
||||
view
|
||||
returns (address daiAddress)
|
||||
{
|
||||
return DAI_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the `Chai` contract.
|
||||
/// @return chaiAddress The `Chai` contract.
|
||||
function _getChaiAddress() internal view returns (address chaiAddress) {
|
||||
function _getChaiAddress()
|
||||
internal
|
||||
view
|
||||
returns (address chaiAddress)
|
||||
{
|
||||
return CHAI_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the 0x `DevUtils` contract address.
|
||||
/// @return devUtils The 0x `DevUtils` contract address.
|
||||
function _getDevUtilsAddress() internal view returns (address devUtils) {
|
||||
function _getDevUtilsAddress()
|
||||
internal
|
||||
view
|
||||
returns (address devUtils)
|
||||
{
|
||||
return DEV_UTILS_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev Overridable way to get the DyDx contract.
|
||||
/// @return exchange The DyDx exchange contract.
|
||||
function _getDydxAddress() internal view returns (address dydxAddress) {
|
||||
function _getDydxAddress()
|
||||
internal
|
||||
view
|
||||
returns (address dydxAddress)
|
||||
{
|
||||
return DYDX_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the GST2 contract address.
|
||||
/// @return gst The GST contract.
|
||||
function _getGstAddress() internal view returns (address gst) {
|
||||
function _getGstAddress()
|
||||
internal
|
||||
view
|
||||
returns (address gst)
|
||||
{
|
||||
return GST_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the GST Collector address.
|
||||
/// @return collector The GST collector address.
|
||||
function _getGstCollectorAddress() internal view returns (address collector) {
|
||||
function _getGstCollectorAddress()
|
||||
internal
|
||||
view
|
||||
returns (address collector)
|
||||
{
|
||||
return GST_COLLECTOR_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the mStable mUSD address.
|
||||
/// @return musd The mStable mUSD address.
|
||||
function _getMUsdAddress() internal view returns (address musd) {
|
||||
function _getMUsdAddress()
|
||||
internal
|
||||
view
|
||||
returns (address musd)
|
||||
{
|
||||
return MUSD_ADDRESS;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the Mooniswap registry address.
|
||||
/// @return registry The Mooniswap registry address.
|
||||
function _getMooniswapAddress() internal view returns (address) {
|
||||
function _getMooniswapAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return MOONISWAP_REGISTRY;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the DODO Registry contract address.
|
||||
/// @return registry The DODO Registry contract address.
|
||||
function _getDODORegistryAddress() internal view returns (address) {
|
||||
function _getDODORegistryAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return DODO_REGISTRY;
|
||||
}
|
||||
|
||||
/// @dev An overridable way to retrieve the DODO Helper contract address.
|
||||
/// @return registry The DODO Helper contract address.
|
||||
function _getDODOHelperAddress() internal view returns (address) {
|
||||
function _getDODOHelperAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return DODO_HELPER;
|
||||
}
|
||||
}
|
||||
|
@@ -18,10 +18,12 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
/**
|
||||
* Utility library of inline functions on addresses
|
||||
*/
|
||||
library LibAddress {
|
||||
|
||||
/**
|
||||
* Returns whether the target address is a contract
|
||||
* @dev This function will return false if invoked during the constructor of a contract,
|
||||
@@ -38,9 +40,8 @@ library LibAddress {
|
||||
// TODO Check this again before the Serenity release, because all addresses will be
|
||||
// contracts then.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
size := extcodesize(account)
|
||||
}
|
||||
assembly { size := extcodesize(account) }
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -22,7 +22,9 @@ import "./LibAddressArrayRichErrors.sol";
|
||||
import "./LibBytes.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
|
||||
|
||||
library LibAddressArray {
|
||||
|
||||
/// @dev Append a new address to an array of addresses.
|
||||
/// The `addressArray` may need to be reallocated to make space
|
||||
/// for the new address. Because of this we return the resulting
|
||||
@@ -30,7 +32,11 @@ library LibAddressArray {
|
||||
/// @param addressArray Array of addresses.
|
||||
/// @param addressToAppend Address to append.
|
||||
/// @return Array of addresses: [... addressArray, addressToAppend]
|
||||
function append(address[] memory addressArray, address addressToAppend) internal pure returns (address[] memory) {
|
||||
function append(address[] memory addressArray, address addressToAppend)
|
||||
internal
|
||||
pure
|
||||
returns (address[] memory)
|
||||
{
|
||||
// Get stats on address array and free memory
|
||||
uint256 freeMemPtr = 0;
|
||||
uint256 addressArrayBeginPtr = 0;
|
||||
@@ -48,7 +54,10 @@ library LibAddressArray {
|
||||
// `freeMemPtr` > `addressArrayEndPtr`: Some value occupies memory after `addressArray`
|
||||
// `freeMemPtr` < `addressArrayEndPtr`: Memory has not been managed properly.
|
||||
if (freeMemPtr < addressArrayEndPtr) {
|
||||
LibRichErrors.rrevert(LibAddressArrayRichErrors.MismanagedMemoryError(freeMemPtr, addressArrayEndPtr));
|
||||
LibRichErrors.rrevert(LibAddressArrayRichErrors.MismanagedMemoryError(
|
||||
freeMemPtr,
|
||||
addressArrayEndPtr
|
||||
));
|
||||
}
|
||||
|
||||
// If free memory begins at the end of `addressArray`
|
||||
@@ -83,8 +92,13 @@ library LibAddressArray {
|
||||
/// @param addressArray Array of addresses.
|
||||
/// @param target Address to search for in array.
|
||||
/// @return True if the addressArray contains the target.
|
||||
function contains(address[] memory addressArray, address target) internal pure returns (bool success) {
|
||||
function contains(address[] memory addressArray, address target)
|
||||
internal
|
||||
pure
|
||||
returns (bool success)
|
||||
{
|
||||
assembly {
|
||||
|
||||
// Calculate byte length of array
|
||||
let arrayByteLen := mul(mload(addressArray), 32)
|
||||
// Calculate beginning of array contents
|
||||
@@ -93,11 +107,8 @@ library LibAddressArray {
|
||||
let arrayContentsEnd := add(arrayContentsStart, arrayByteLen)
|
||||
|
||||
// Loop through array
|
||||
for {
|
||||
let i := arrayContentsStart
|
||||
} lt(i, arrayContentsEnd) {
|
||||
i := add(i, 32)
|
||||
} {
|
||||
for {let i:= arrayContentsStart} lt(i, arrayContentsEnd) {i := add(i, 32)} {
|
||||
|
||||
// Load array element
|
||||
let arrayElement := mload(i)
|
||||
|
||||
@@ -117,11 +128,13 @@ library LibAddressArray {
|
||||
/// @param addressArray Array of addresses.
|
||||
/// @param target Address to search for in array.
|
||||
/// @return Existence and index of the target in the array.
|
||||
function indexOf(
|
||||
address[] memory addressArray,
|
||||
address target
|
||||
) internal pure returns (bool success, uint256 index) {
|
||||
function indexOf(address[] memory addressArray, address target)
|
||||
internal
|
||||
pure
|
||||
returns (bool success, uint256 index)
|
||||
{
|
||||
assembly {
|
||||
|
||||
// Calculate byte length of array
|
||||
let arrayByteLen := mul(mload(addressArray), 32)
|
||||
// Calculate beginning of array contents
|
||||
@@ -130,11 +143,8 @@ library LibAddressArray {
|
||||
let arrayContentsEnd := add(arrayContentsStart, arrayByteLen)
|
||||
|
||||
// Loop through array
|
||||
for {
|
||||
let i := arrayContentsStart
|
||||
} lt(i, arrayContentsEnd) {
|
||||
i := add(i, 32)
|
||||
} {
|
||||
for {let i:= arrayContentsStart} lt(i, arrayContentsEnd) {i := add(i, 32)} {
|
||||
|
||||
// Load array element
|
||||
let arrayElement := mload(i)
|
||||
|
||||
|
@@ -18,14 +18,26 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
library LibAddressArrayRichErrors {
|
||||
// bytes4(keccak256("MismanagedMemoryError(uint256,uint256)"))
|
||||
bytes4 internal constant MISMANAGED_MEMORY_ERROR_SELECTOR = 0x5fc83722;
|
||||
|
||||
library LibAddressArrayRichErrors {
|
||||
|
||||
// bytes4(keccak256("MismanagedMemoryError(uint256,uint256)"))
|
||||
bytes4 internal constant MISMANAGED_MEMORY_ERROR_SELECTOR =
|
||||
0x5fc83722;
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
function MismanagedMemoryError(
|
||||
uint256 freeMemPtr,
|
||||
uint256 addressArrayEndPtr
|
||||
) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(MISMANAGED_MEMORY_ERROR_SELECTOR, freeMemPtr, addressArrayEndPtr);
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
MISMANAGED_MEMORY_ERROR_SELECTOR,
|
||||
freeMemPtr,
|
||||
addressArrayEndPtr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -18,46 +18,102 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibAuthorizableRichErrors {
|
||||
|
||||
// bytes4(keccak256("AuthorizedAddressMismatchError(address,address)"))
|
||||
bytes4 internal constant AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR = 0x140a84db;
|
||||
bytes4 internal constant AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR =
|
||||
0x140a84db;
|
||||
|
||||
// bytes4(keccak256("IndexOutOfBoundsError(uint256,uint256)"))
|
||||
bytes4 internal constant INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR = 0xe9f83771;
|
||||
bytes4 internal constant INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR =
|
||||
0xe9f83771;
|
||||
|
||||
// bytes4(keccak256("SenderNotAuthorizedError(address)"))
|
||||
bytes4 internal constant SENDER_NOT_AUTHORIZED_ERROR_SELECTOR = 0xb65a25b9;
|
||||
bytes4 internal constant SENDER_NOT_AUTHORIZED_ERROR_SELECTOR =
|
||||
0xb65a25b9;
|
||||
|
||||
// bytes4(keccak256("TargetAlreadyAuthorizedError(address)"))
|
||||
bytes4 internal constant TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR = 0xde16f1a0;
|
||||
bytes4 internal constant TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR =
|
||||
0xde16f1a0;
|
||||
|
||||
// bytes4(keccak256("TargetNotAuthorizedError(address)"))
|
||||
bytes4 internal constant TARGET_NOT_AUTHORIZED_ERROR_SELECTOR = 0xeb5108a2;
|
||||
bytes4 internal constant TARGET_NOT_AUTHORIZED_ERROR_SELECTOR =
|
||||
0xeb5108a2;
|
||||
|
||||
// bytes4(keccak256("ZeroCantBeAuthorizedError()"))
|
||||
bytes internal constant ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES = hex"57654fe4";
|
||||
bytes internal constant ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES =
|
||||
hex"57654fe4";
|
||||
|
||||
function AuthorizedAddressMismatchError(address authorized, address target) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR, authorized, target);
|
||||
// solhint-disable func-name-mixedcase
|
||||
function AuthorizedAddressMismatchError(
|
||||
address authorized,
|
||||
address target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR,
|
||||
authorized,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
function IndexOutOfBoundsError(uint256 index, uint256 length) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR, index, length);
|
||||
function IndexOutOfBoundsError(
|
||||
uint256 index,
|
||||
uint256 length
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR,
|
||||
index,
|
||||
length
|
||||
);
|
||||
}
|
||||
|
||||
function SenderNotAuthorizedError(address sender) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(SENDER_NOT_AUTHORIZED_ERROR_SELECTOR, sender);
|
||||
function SenderNotAuthorizedError(address sender)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
SENDER_NOT_AUTHORIZED_ERROR_SELECTOR,
|
||||
sender
|
||||
);
|
||||
}
|
||||
|
||||
function TargetAlreadyAuthorizedError(address target) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR, target);
|
||||
function TargetAlreadyAuthorizedError(address target)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
function TargetNotAuthorizedError(address target) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(TARGET_NOT_AUTHORIZED_ERROR_SELECTOR, target);
|
||||
function TargetNotAuthorizedError(address target)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
TARGET_NOT_AUTHORIZED_ERROR_SELECTOR,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
function ZeroCantBeAuthorizedError() internal pure returns (bytes memory) {
|
||||
function ZeroCantBeAuthorizedError()
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES;
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,9 @@ pragma solidity ^0.5.9;
|
||||
import "./LibBytesRichErrors.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
|
||||
|
||||
library LibBytes {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
/// @dev Gets the memory address for a byte array.
|
||||
@@ -29,7 +31,11 @@ library LibBytes {
|
||||
/// @return memoryAddress Memory address of byte array. This
|
||||
/// points to the header of the byte array which contains
|
||||
/// the length.
|
||||
function rawAddress(bytes memory input) internal pure returns (uint256 memoryAddress) {
|
||||
function rawAddress(bytes memory input)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 memoryAddress)
|
||||
{
|
||||
assembly {
|
||||
memoryAddress := input
|
||||
}
|
||||
@@ -39,7 +45,11 @@ library LibBytes {
|
||||
/// @dev Gets the memory address for the contents of a byte array.
|
||||
/// @param input Byte array to lookup.
|
||||
/// @return memoryAddress Memory address of the contents of the byte array.
|
||||
function contentAddress(bytes memory input) internal pure returns (uint256 memoryAddress) {
|
||||
function contentAddress(bytes memory input)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 memoryAddress)
|
||||
{
|
||||
assembly {
|
||||
memoryAddress := add(input, 32)
|
||||
}
|
||||
@@ -50,7 +60,14 @@ library LibBytes {
|
||||
/// @param dest memory address to copy bytes to.
|
||||
/// @param source memory address to copy bytes from.
|
||||
/// @param length number of bytes to copy.
|
||||
function memCopy(uint256 dest, uint256 source, uint256 length) internal pure {
|
||||
function memCopy(
|
||||
uint256 dest,
|
||||
uint256 source,
|
||||
uint256 length
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (length < 32) {
|
||||
// Handle a partial word by reading destination and masking
|
||||
// off the bits we are interested in.
|
||||
@@ -101,11 +118,8 @@ library LibBytes {
|
||||
// Copy whole words front to back
|
||||
// Note: the first check is always true,
|
||||
// this could have been a do-while loop.
|
||||
for {
|
||||
|
||||
} lt(source, sEnd) {
|
||||
|
||||
} {
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
for {} lt(source, sEnd) {} {
|
||||
mstore(dest, mload(source))
|
||||
source := add(source, 32)
|
||||
dest := add(dest, 32)
|
||||
@@ -135,11 +149,8 @@ library LibBytes {
|
||||
// 2**255, so they can be safely re-interpreted as signed.
|
||||
// Note: the first check is always true,
|
||||
// this could have been a do-while loop.
|
||||
for {
|
||||
|
||||
} slt(dest, dEnd) {
|
||||
|
||||
} {
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
for {} slt(dest, dEnd) {} {
|
||||
mstore(dEnd, mload(sEnd))
|
||||
sEnd := sub(sEnd, 32)
|
||||
dEnd := sub(dEnd, 32)
|
||||
@@ -157,31 +168,39 @@ library LibBytes {
|
||||
/// @param from The starting index for the slice (inclusive).
|
||||
/// @param to The final index for the slice (exclusive).
|
||||
/// @return result The slice containing bytes at indices [from, to)
|
||||
function slice(bytes memory b, uint256 from, uint256 to) internal pure returns (bytes memory result) {
|
||||
function slice(
|
||||
bytes memory b,
|
||||
uint256 from,
|
||||
uint256 to
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory result)
|
||||
{
|
||||
// Ensure that the from and to positions are valid positions for a slice within
|
||||
// the byte array that is being used.
|
||||
if (from > to) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
));
|
||||
}
|
||||
if (to > b.length) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
));
|
||||
}
|
||||
|
||||
// Create a new bytes structure and copy contents
|
||||
result = new bytes(to - from);
|
||||
memCopy(result.contentAddress(), b.contentAddress() + from, result.length);
|
||||
memCopy(
|
||||
result.contentAddress(),
|
||||
b.contentAddress() + from,
|
||||
result.length
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -191,26 +210,30 @@ library LibBytes {
|
||||
/// @param to The final index for the slice (exclusive).
|
||||
/// @return result The slice containing bytes at indices [from, to)
|
||||
/// @dev When `from == 0`, the original array will match the slice. In other cases its state will be corrupted.
|
||||
function sliceDestructive(bytes memory b, uint256 from, uint256 to) internal pure returns (bytes memory result) {
|
||||
function sliceDestructive(
|
||||
bytes memory b,
|
||||
uint256 from,
|
||||
uint256 to
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory result)
|
||||
{
|
||||
// Ensure that the from and to positions are valid positions for a slice within
|
||||
// the byte array that is being used.
|
||||
if (from > to) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
));
|
||||
}
|
||||
if (to > b.length) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
));
|
||||
}
|
||||
|
||||
// Create a new bytes structure around [from, to) in-place.
|
||||
@@ -224,15 +247,17 @@ library LibBytes {
|
||||
/// @dev Pops the last byte off of a byte array by modifying its length.
|
||||
/// @param b Byte array that will be modified.
|
||||
/// @return The byte that was popped off.
|
||||
function popLastByte(bytes memory b) internal pure returns (bytes1 result) {
|
||||
function popLastByte(bytes memory b)
|
||||
internal
|
||||
pure
|
||||
returns (bytes1 result)
|
||||
{
|
||||
if (b.length == 0) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanZeroRequired,
|
||||
b.length,
|
||||
0
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanZeroRequired,
|
||||
b.length,
|
||||
0
|
||||
));
|
||||
}
|
||||
|
||||
// Store last byte.
|
||||
@@ -250,7 +275,14 @@ library LibBytes {
|
||||
/// @param lhs First byte array to compare.
|
||||
/// @param rhs Second byte array to compare.
|
||||
/// @return True if arrays are the same. False otherwise.
|
||||
function equals(bytes memory lhs, bytes memory rhs) internal pure returns (bool equal) {
|
||||
function equals(
|
||||
bytes memory lhs,
|
||||
bytes memory rhs
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool equal)
|
||||
{
|
||||
// Keccak gas cost is 30 + numWords * 6. This is a cheap way to compare.
|
||||
// We early exit on unequal lengths, but keccak would also correctly
|
||||
// handle this.
|
||||
@@ -261,15 +293,20 @@ library LibBytes {
|
||||
/// @param b Byte array containing an address.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @return address from byte array.
|
||||
function readAddress(bytes memory b, uint256 index) internal pure returns (address result) {
|
||||
function readAddress(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (address result)
|
||||
{
|
||||
if (b.length < index + 20) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
));
|
||||
}
|
||||
|
||||
// Add offset to index:
|
||||
@@ -291,15 +328,20 @@ library LibBytes {
|
||||
/// @param b Byte array to insert address into.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @param input Address to put into byte array.
|
||||
function writeAddress(bytes memory b, uint256 index, address input) internal pure {
|
||||
function writeAddress(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
address input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (b.length < index + 20) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
));
|
||||
}
|
||||
|
||||
// Add offset to index:
|
||||
@@ -335,15 +377,20 @@ library LibBytes {
|
||||
/// @param b Byte array containing a bytes32 value.
|
||||
/// @param index Index in byte array of bytes32 value.
|
||||
/// @return bytes32 value from byte array.
|
||||
function readBytes32(bytes memory b, uint256 index) internal pure returns (bytes32 result) {
|
||||
function readBytes32(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
if (b.length < index + 32) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
@@ -360,15 +407,20 @@ library LibBytes {
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input bytes32 to put into byte array.
|
||||
function writeBytes32(bytes memory b, uint256 index, bytes32 input) internal pure {
|
||||
function writeBytes32(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
bytes32 input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (b.length < index + 32) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
@@ -384,7 +436,14 @@ library LibBytes {
|
||||
/// @param b Byte array containing a uint256 value.
|
||||
/// @param index Index in byte array of uint256 value.
|
||||
/// @return uint256 value from byte array.
|
||||
function readUint256(bytes memory b, uint256 index) internal pure returns (uint256 result) {
|
||||
function readUint256(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 result)
|
||||
{
|
||||
result = uint256(readBytes32(b, index));
|
||||
return result;
|
||||
}
|
||||
@@ -393,7 +452,14 @@ library LibBytes {
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input uint256 to put into byte array.
|
||||
function writeUint256(bytes memory b, uint256 index, uint256 input) internal pure {
|
||||
function writeUint256(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
uint256 input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
writeBytes32(b, index, bytes32(input));
|
||||
}
|
||||
|
||||
@@ -401,15 +467,20 @@ library LibBytes {
|
||||
/// @param b Byte array containing a bytes4 value.
|
||||
/// @param index Index in byte array of bytes4 value.
|
||||
/// @return bytes4 value from byte array.
|
||||
function readBytes4(bytes memory b, uint256 index) internal pure returns (bytes4 result) {
|
||||
function readBytes4(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes4 result)
|
||||
{
|
||||
if (b.length < index + 4) {
|
||||
LibRichErrors.rrevert(
|
||||
LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsFourRequired,
|
||||
b.length,
|
||||
index + 4
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError(
|
||||
LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsFourRequired,
|
||||
b.length,
|
||||
index + 4
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 32 byte length field
|
||||
@@ -430,7 +501,10 @@ library LibBytes {
|
||||
/// Increasing length may lead to appending adjacent in-memory bytes to the end of the byte array.
|
||||
/// @param b Bytes array to write new length to.
|
||||
/// @param length New length of byte array.
|
||||
function writeLength(bytes memory b, uint256 length) internal pure {
|
||||
function writeLength(bytes memory b, uint256 length)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
assembly {
|
||||
mstore(b, length)
|
||||
}
|
||||
|
@@ -18,7 +18,9 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibBytesRichErrors {
|
||||
|
||||
enum InvalidByteOperationErrorCodes {
|
||||
FromLessThanOrEqualsToRequired,
|
||||
ToLessThanOrEqualsLengthRequired,
|
||||
@@ -31,13 +33,24 @@ library LibBytesRichErrors {
|
||||
}
|
||||
|
||||
// bytes4(keccak256("InvalidByteOperationError(uint8,uint256,uint256)"))
|
||||
bytes4 internal constant INVALID_BYTE_OPERATION_ERROR_SELECTOR = 0x28006595;
|
||||
bytes4 internal constant INVALID_BYTE_OPERATION_ERROR_SELECTOR =
|
||||
0x28006595;
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
function InvalidByteOperationError(
|
||||
InvalidByteOperationErrorCodes errorCode,
|
||||
uint256 offset,
|
||||
uint256 required
|
||||
) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(INVALID_BYTE_OPERATION_ERROR_SELECTOR, errorCode, offset, required);
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
INVALID_BYTE_OPERATION_ERROR_SELECTOR,
|
||||
errorCode,
|
||||
offset,
|
||||
required
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,10 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract LibEIP1271 {
|
||||
|
||||
/// @dev Magic bytes returned by EIP1271 wallets on success.
|
||||
/// @return 0 Magic bytes.
|
||||
bytes4 public constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
|
||||
bytes4 constant public EIP1271_MAGIC_VALUE = 0x20c13b0b;
|
||||
}
|
||||
|
@@ -18,7 +18,9 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibEIP712 {
|
||||
|
||||
// Hash of the EIP712 Domain Separator Schema
|
||||
// keccak256(abi.encodePacked(
|
||||
// "EIP712Domain(",
|
||||
@@ -28,8 +30,7 @@ library LibEIP712 {
|
||||
// "address verifyingContract",
|
||||
// ")"
|
||||
// ))
|
||||
bytes32 internal constant _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH =
|
||||
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
|
||||
bytes32 constant internal _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
|
||||
|
||||
/// @dev Calculates a EIP712 domain separator.
|
||||
/// @param name The EIP712 domain name.
|
||||
@@ -41,7 +42,11 @@ library LibEIP712 {
|
||||
string memory version,
|
||||
uint256 chainId,
|
||||
address verifyingContract
|
||||
) internal pure returns (bytes32 result) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
bytes32 schemaHash = _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;
|
||||
|
||||
// Assembly for more efficient computing:
|
||||
@@ -79,7 +84,11 @@ library LibEIP712 {
|
||||
/// with getDomainHash().
|
||||
/// @param hashStruct The EIP712 hash struct.
|
||||
/// @return EIP712 hash applied to the given EIP712 Domain.
|
||||
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct) internal pure returns (bytes32 result) {
|
||||
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
// Assembly for more efficient computing:
|
||||
// keccak256(abi.encodePacked(
|
||||
// EIP191_HEADER,
|
||||
@@ -91,9 +100,9 @@ library LibEIP712 {
|
||||
// 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
|
||||
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)
|
||||
|
@@ -2,7 +2,9 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./LibSafeMath.sol";
|
||||
|
||||
|
||||
library LibFractions {
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Safely adds two fractions `n1/d1 + n2/d2`
|
||||
@@ -17,14 +19,23 @@ library LibFractions {
|
||||
uint256 d1,
|
||||
uint256 n2,
|
||||
uint256 d2
|
||||
) internal pure returns (uint256 numerator, uint256 denominator) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 numerator,
|
||||
uint256 denominator
|
||||
)
|
||||
{
|
||||
if (n1 == 0) {
|
||||
return (numerator = n2, denominator = d2);
|
||||
}
|
||||
if (n2 == 0) {
|
||||
return (numerator = n1, denominator = d1);
|
||||
}
|
||||
numerator = n1.safeMul(d2).safeAdd(n2.safeMul(d1));
|
||||
numerator = n1
|
||||
.safeMul(d2)
|
||||
.safeAdd(n2.safeMul(d1));
|
||||
denominator = d1.safeMul(d2);
|
||||
return (numerator, denominator);
|
||||
}
|
||||
@@ -41,7 +52,14 @@ library LibFractions {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 maxValue
|
||||
) internal pure returns (uint256 scaledNumerator, uint256 scaledDenominator) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 scaledNumerator,
|
||||
uint256 scaledDenominator
|
||||
)
|
||||
{
|
||||
// If either the numerator or the denominator are > `maxValue`,
|
||||
// re-scale them by `maxValue` to prevent overflows in future operations.
|
||||
if (numerator > maxValue || denominator > maxValue) {
|
||||
@@ -65,7 +83,14 @@ library LibFractions {
|
||||
function normalize(
|
||||
uint256 numerator,
|
||||
uint256 denominator
|
||||
) internal pure returns (uint256 scaledNumerator, uint256 scaledDenominator) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
uint256 scaledNumerator,
|
||||
uint256 scaledDenominator
|
||||
)
|
||||
{
|
||||
return normalize(numerator, denominator, 2 ** 127);
|
||||
}
|
||||
|
||||
@@ -82,15 +107,25 @@ library LibFractions {
|
||||
uint256 n2,
|
||||
uint256 d2,
|
||||
uint256 s
|
||||
) internal pure returns (uint256 result) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 result)
|
||||
{
|
||||
if (s == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (n2 == 0) {
|
||||
return result = s.safeMul(n1).safeDiv(d1);
|
||||
return result = s
|
||||
.safeMul(n1)
|
||||
.safeDiv(d1);
|
||||
}
|
||||
uint256 numerator = n1.safeMul(d2).safeSub(n2.safeMul(d1));
|
||||
uint256 numerator = n1
|
||||
.safeMul(d2)
|
||||
.safeSub(n2.safeMul(d1));
|
||||
uint256 tmp = numerator.safeDiv(d2);
|
||||
return s.safeMul(tmp).safeDiv(d1);
|
||||
return s
|
||||
.safeMul(tmp)
|
||||
.safeDiv(d1);
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,9 @@ import "./LibSafeMath.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
import "./LibMathRichErrors.sol";
|
||||
|
||||
|
||||
library LibMath {
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
@@ -35,9 +37,21 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
if (isRoundingErrorFloor(numerator, denominator, target)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(numerator, denominator, target));
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
@@ -54,15 +68,29 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
if (isRoundingErrorCeil(numerator, denominator, target)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(numerator, denominator, target));
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
// 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 = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -76,7 +104,11 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -90,11 +122,17 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
// 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 = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -108,7 +146,11 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (bool isError) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
|
||||
}
|
||||
@@ -139,7 +181,11 @@ library LibMath {
|
||||
// 1000 * remainder < numerator * target
|
||||
// so we have a rounding error iff:
|
||||
// 1000 * remainder >= numerator * target
|
||||
uint256 remainder = mulmod(target, numerator, denominator);
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
}
|
||||
@@ -153,7 +199,11 @@ library LibMath {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (bool isError) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
|
||||
}
|
||||
@@ -166,7 +216,11 @@ library LibMath {
|
||||
return false;
|
||||
}
|
||||
// Compute remainder as before
|
||||
uint256 remainder = mulmod(target, numerator, denominator);
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
remainder = denominator.safeSub(remainder) % denominator;
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
|
@@ -1,13 +1,22 @@
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibMathRichErrors {
|
||||
|
||||
// bytes4(keccak256("DivisionByZeroError()"))
|
||||
bytes internal constant DIVISION_BY_ZERO_ERROR = hex"a791837c";
|
||||
bytes internal constant DIVISION_BY_ZERO_ERROR =
|
||||
hex"a791837c";
|
||||
|
||||
// bytes4(keccak256("RoundingError(uint256,uint256,uint256)"))
|
||||
bytes4 internal constant ROUNDING_ERROR_SELECTOR = 0x339f3de2;
|
||||
bytes4 internal constant ROUNDING_ERROR_SELECTOR =
|
||||
0x339f3de2;
|
||||
|
||||
function DivisionByZeroError() internal pure returns (bytes memory) {
|
||||
// solhint-disable func-name-mixedcase
|
||||
function DivisionByZeroError()
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return DIVISION_BY_ZERO_ERROR;
|
||||
}
|
||||
|
||||
@@ -15,7 +24,16 @@ library LibMathRichErrors {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(ROUNDING_ERROR_SELECTOR, numerator, denominator, target);
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
ROUNDING_ERROR_SELECTOR,
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,37 @@
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibOwnableRichErrors {
|
||||
|
||||
// bytes4(keccak256("OnlyOwnerError(address,address)"))
|
||||
bytes4 internal constant ONLY_OWNER_ERROR_SELECTOR = 0x1de45ad1;
|
||||
bytes4 internal constant ONLY_OWNER_ERROR_SELECTOR =
|
||||
0x1de45ad1;
|
||||
|
||||
// bytes4(keccak256("TransferOwnerToZeroError()"))
|
||||
bytes internal constant TRANSFER_OWNER_TO_ZERO_ERROR_BYTES = hex"e69edc3e";
|
||||
bytes internal constant TRANSFER_OWNER_TO_ZERO_ERROR_BYTES =
|
||||
hex"e69edc3e";
|
||||
|
||||
function OnlyOwnerError(address sender, address owner) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(ONLY_OWNER_ERROR_SELECTOR, sender, owner);
|
||||
// solhint-disable func-name-mixedcase
|
||||
function OnlyOwnerError(
|
||||
address sender,
|
||||
address owner
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
ONLY_OWNER_ERROR_SELECTOR,
|
||||
sender,
|
||||
owner
|
||||
);
|
||||
}
|
||||
|
||||
function TransferOwnerToZeroError() internal pure returns (bytes memory) {
|
||||
function TransferOwnerToZeroError()
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return TRANSFER_OWNER_TO_ZERO_ERROR_BYTES;
|
||||
}
|
||||
}
|
||||
|
@@ -18,11 +18,19 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
library LibReentrancyGuardRichErrors {
|
||||
// bytes4(keccak256("IllegalReentrancyError()"))
|
||||
bytes internal constant ILLEGAL_REENTRANCY_ERROR_SELECTOR_BYTES = hex"0c3b823f";
|
||||
|
||||
function IllegalReentrancyError() internal pure returns (bytes memory) {
|
||||
library LibReentrancyGuardRichErrors {
|
||||
|
||||
// bytes4(keccak256("IllegalReentrancyError()"))
|
||||
bytes internal constant ILLEGAL_REENTRANCY_ERROR_SELECTOR_BYTES =
|
||||
hex"0c3b823f";
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
function IllegalReentrancyError()
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return ILLEGAL_REENTRANCY_ERROR_SELECTOR_BYTES;
|
||||
}
|
||||
}
|
||||
|
@@ -18,22 +18,39 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
library LibRichErrors {
|
||||
// bytes4(keccak256("Error(string)"))
|
||||
bytes4 internal constant STANDARD_ERROR_SELECTOR = 0x08c379a0;
|
||||
|
||||
library LibRichErrors {
|
||||
|
||||
// bytes4(keccak256("Error(string)"))
|
||||
bytes4 internal constant STANDARD_ERROR_SELECTOR =
|
||||
0x08c379a0;
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
/// @dev ABI encode a standard, string revert error payload.
|
||||
/// This is the same payload that would be included by a `revert(string)`
|
||||
/// solidity statement. It has the function signature `Error(string)`.
|
||||
/// @param message The error string.
|
||||
/// @return The ABI encoded error.
|
||||
function StandardError(string memory message) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(STANDARD_ERROR_SELECTOR, bytes(message));
|
||||
function StandardError(
|
||||
string memory message
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
STANDARD_ERROR_SELECTOR,
|
||||
bytes(message)
|
||||
);
|
||||
}
|
||||
// solhint-enable func-name-mixedcase
|
||||
|
||||
/// @dev Reverts an encoded rich revert reason `errorData`.
|
||||
/// @param errorData ABI encoded error data.
|
||||
function rrevert(bytes memory errorData) internal pure {
|
||||
function rrevert(bytes memory errorData)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
assembly {
|
||||
revert(add(errorData, 0x20), mload(errorData))
|
||||
}
|
||||
|
@@ -3,62 +3,88 @@ pragma solidity ^0.5.9;
|
||||
import "./LibRichErrors.sol";
|
||||
import "./LibSafeMathRichErrors.sol";
|
||||
|
||||
|
||||
library LibSafeMath {
|
||||
function safeMul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
|
||||
function safeMul(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint256 c = a * b;
|
||||
if (c / a != b) {
|
||||
LibRichErrors.rrevert(
|
||||
LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeDiv(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (b == 0) {
|
||||
LibRichErrors.rrevert(
|
||||
LibSafeMathRichErrors.Uint256BinOpError(LibSafeMathRichErrors.BinOpErrorCodes.DIVISION_BY_ZERO, a, b)
|
||||
);
|
||||
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
uint256 c = a / b;
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeSub(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (b > a) {
|
||||
LibRichErrors.rrevert(
|
||||
LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeAdd(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
uint256 c = a + b;
|
||||
if (c < a) {
|
||||
LibRichErrors.rrevert(
|
||||
LibSafeMathRichErrors.Uint256BinOpError(LibSafeMathRichErrors.BinOpErrorCodes.ADDITION_OVERFLOW, a, b)
|
||||
);
|
||||
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError(
|
||||
LibSafeMathRichErrors.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function max256(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function max256(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return a >= b ? a : b;
|
||||
}
|
||||
|
||||
function min256(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function min256(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,15 @@
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibSafeMathRichErrors {
|
||||
|
||||
// bytes4(keccak256("Uint256BinOpError(uint8,uint256,uint256)"))
|
||||
bytes4 internal constant UINT256_BINOP_ERROR_SELECTOR = 0xe946c1bb;
|
||||
bytes4 internal constant UINT256_BINOP_ERROR_SELECTOR =
|
||||
0xe946c1bb;
|
||||
|
||||
// bytes4(keccak256("Uint256DowncastError(uint8,uint256)"))
|
||||
bytes4 internal constant UINT256_DOWNCAST_ERROR_SELECTOR = 0xc996af7b;
|
||||
bytes4 internal constant UINT256_DOWNCAST_ERROR_SELECTOR =
|
||||
0xc996af7b;
|
||||
|
||||
enum BinOpErrorCodes {
|
||||
ADDITION_OVERFLOW,
|
||||
@@ -20,11 +24,36 @@ library LibSafeMathRichErrors {
|
||||
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT96
|
||||
}
|
||||
|
||||
function Uint256BinOpError(BinOpErrorCodes errorCode, uint256 a, uint256 b) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(UINT256_BINOP_ERROR_SELECTOR, errorCode, a, b);
|
||||
// solhint-disable func-name-mixedcase
|
||||
function Uint256BinOpError(
|
||||
BinOpErrorCodes errorCode,
|
||||
uint256 a,
|
||||
uint256 b
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
UINT256_BINOP_ERROR_SELECTOR,
|
||||
errorCode,
|
||||
a,
|
||||
b
|
||||
);
|
||||
}
|
||||
|
||||
function Uint256DowncastError(DowncastErrorCodes errorCode, uint256 a) internal pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(UINT256_DOWNCAST_ERROR_SELECTOR, errorCode, a);
|
||||
function Uint256DowncastError(
|
||||
DowncastErrorCodes errorCode,
|
||||
uint256 a
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
UINT256_DOWNCAST_ERROR_SELECTOR,
|
||||
errorCode,
|
||||
a
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -22,12 +22,17 @@ import "./interfaces/IOwnable.sol";
|
||||
import "./LibOwnableRichErrors.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
|
||||
contract Ownable is IOwnable {
|
||||
|
||||
contract Ownable is
|
||||
IOwnable
|
||||
{
|
||||
/// @dev The owner of this contract.
|
||||
/// @return 0 The owner address.
|
||||
address public owner;
|
||||
|
||||
constructor() public {
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
@@ -38,7 +43,10 @@ contract Ownable is IOwnable {
|
||||
|
||||
/// @dev Change the owner of this contract.
|
||||
/// @param newOwner New owner address.
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
function transferOwnership(address newOwner)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
if (newOwner == address(0)) {
|
||||
LibRichErrors.rrevert(LibOwnableRichErrors.TransferOwnerToZeroError());
|
||||
} else {
|
||||
@@ -47,9 +55,15 @@ contract Ownable is IOwnable {
|
||||
}
|
||||
}
|
||||
|
||||
function _assertSenderIsOwner() internal view {
|
||||
function _assertSenderIsOwner()
|
||||
internal
|
||||
view
|
||||
{
|
||||
if (msg.sender != owner) {
|
||||
LibRichErrors.rrevert(LibOwnableRichErrors.OnlyOwnerError(msg.sender, owner));
|
||||
LibRichErrors.rrevert(LibOwnableRichErrors.OnlyOwnerError(
|
||||
msg.sender,
|
||||
owner
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,9 @@ pragma solidity ^0.5.9;
|
||||
import "./LibReentrancyGuardRichErrors.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
|
||||
|
||||
contract ReentrancyGuard {
|
||||
|
||||
// Locked state of mutex.
|
||||
bool private _locked = false;
|
||||
|
||||
@@ -33,16 +35,22 @@ contract ReentrancyGuard {
|
||||
_unlockMutex();
|
||||
}
|
||||
|
||||
function _lockMutexOrThrowIfAlreadyLocked() internal {
|
||||
function _lockMutexOrThrowIfAlreadyLocked()
|
||||
internal
|
||||
{
|
||||
// Ensure mutex is unlocked.
|
||||
if (_locked) {
|
||||
LibRichErrors.rrevert(LibReentrancyGuardRichErrors.IllegalReentrancyError());
|
||||
LibRichErrors.rrevert(
|
||||
LibReentrancyGuardRichErrors.IllegalReentrancyError()
|
||||
);
|
||||
}
|
||||
// Lock mutex.
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
function _unlockMutex() internal {
|
||||
function _unlockMutex()
|
||||
internal
|
||||
{
|
||||
// Unlock mutex.
|
||||
_locked = false;
|
||||
}
|
||||
|
@@ -20,23 +20,27 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./ReentrancyGuard.sol";
|
||||
|
||||
contract Refundable is ReentrancyGuard {
|
||||
|
||||
contract Refundable is
|
||||
ReentrancyGuard
|
||||
{
|
||||
|
||||
// This bool is used by the refund modifier to allow for lazily evaluated refunds.
|
||||
bool internal _shouldNotRefund;
|
||||
|
||||
modifier refundFinalBalance() {
|
||||
modifier refundFinalBalance {
|
||||
_;
|
||||
_refundNonZeroBalanceIfEnabled();
|
||||
}
|
||||
|
||||
modifier refundFinalBalanceNoReentry() {
|
||||
modifier refundFinalBalanceNoReentry {
|
||||
_lockMutexOrThrowIfAlreadyLocked();
|
||||
_;
|
||||
_refundNonZeroBalanceIfEnabled();
|
||||
_unlockMutex();
|
||||
}
|
||||
|
||||
modifier disableRefundUntilEnd() {
|
||||
modifier disableRefundUntilEnd {
|
||||
if (_areRefundsDisabled()) {
|
||||
_;
|
||||
} else {
|
||||
@@ -46,29 +50,41 @@ contract Refundable is ReentrancyGuard {
|
||||
}
|
||||
}
|
||||
|
||||
function _refundNonZeroBalanceIfEnabled() internal {
|
||||
function _refundNonZeroBalanceIfEnabled()
|
||||
internal
|
||||
{
|
||||
if (!_areRefundsDisabled()) {
|
||||
_refundNonZeroBalance();
|
||||
}
|
||||
}
|
||||
|
||||
function _refundNonZeroBalance() internal {
|
||||
function _refundNonZeroBalance()
|
||||
internal
|
||||
{
|
||||
uint256 balance = address(this).balance;
|
||||
if (balance > 0) {
|
||||
msg.sender.transfer(balance);
|
||||
}
|
||||
}
|
||||
|
||||
function _disableRefund() internal {
|
||||
function _disableRefund()
|
||||
internal
|
||||
{
|
||||
_shouldNotRefund = true;
|
||||
}
|
||||
|
||||
function _enableAndRefundNonZeroBalance() internal {
|
||||
function _enableAndRefundNonZeroBalance()
|
||||
internal
|
||||
{
|
||||
_shouldNotRefund = false;
|
||||
_refundNonZeroBalance();
|
||||
}
|
||||
|
||||
function _areRefundsDisabled() internal view returns (bool) {
|
||||
function _areRefundsDisabled()
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _shouldNotRefund;
|
||||
}
|
||||
}
|
||||
|
@@ -20,27 +20,45 @@ pragma solidity ^0.5.9;
|
||||
|
||||
import "./IOwnable.sol";
|
||||
|
||||
contract IAuthorizable is IOwnable {
|
||||
|
||||
contract IAuthorizable is
|
||||
IOwnable
|
||||
{
|
||||
// Event logged when a new address is authorized.
|
||||
event AuthorizedAddressAdded(address indexed target, address indexed caller);
|
||||
event AuthorizedAddressAdded(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
// Event logged when a currently authorized address is unauthorized.
|
||||
event AuthorizedAddressRemoved(address indexed target, address indexed caller);
|
||||
event AuthorizedAddressRemoved(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target) external;
|
||||
function addAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target) external;
|
||||
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;
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses() external view returns (address[] memory);
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
||||
|
@@ -18,7 +18,9 @@
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract IOwnable {
|
||||
|
||||
/// @dev Emitted by Ownable when ownership is transferred.
|
||||
/// @param previousOwner The previous owner of the contract.
|
||||
/// @param newOwner The new owner of the contract.
|
||||
@@ -26,5 +28,6 @@ contract IOwnable {
|
||||
|
||||
/// @dev Transfers ownership of the contract to a new address.
|
||||
/// @param newOwner The address that will become the owner.
|
||||
function transferOwnership(address newOwner) public;
|
||||
function transferOwnership(address newOwner)
|
||||
public;
|
||||
}
|
||||
|
@@ -24,9 +24,14 @@ import "./errors/LibRichErrorsV06.sol";
|
||||
import "./errors/LibAuthorizableRichErrorsV06.sol";
|
||||
import "./OwnableV06.sol";
|
||||
|
||||
contract AuthorizableV06 is OwnableV06, IAuthorizableV06 {
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract AuthorizableV06 is
|
||||
OwnableV06,
|
||||
IAuthorizableV06
|
||||
{
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized() {
|
||||
modifier onlyAuthorized {
|
||||
_assertSenderIsAuthorized();
|
||||
_;
|
||||
}
|
||||
@@ -34,24 +39,35 @@ contract AuthorizableV06 is OwnableV06, IAuthorizableV06 {
|
||||
// @dev Whether an address is authorized to call privileged functions.
|
||||
// @param 0 Address to query.
|
||||
// @return 0 Whether the address is authorized.
|
||||
mapping(address => bool) public override authorized;
|
||||
mapping (address => bool) public override authorized;
|
||||
// @dev Whether an address is authorized to call privileged functions.
|
||||
// @param 0 Index of authorized address.
|
||||
// @return 0 Authorized address.
|
||||
address[] public override authorities;
|
||||
|
||||
/// @dev Initializes the `owner` address.
|
||||
constructor() public OwnableV06() {}
|
||||
constructor()
|
||||
public
|
||||
OwnableV06()
|
||||
{}
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target) external override onlyOwner {
|
||||
function addAuthorizedAddress(address target)
|
||||
external
|
||||
override
|
||||
onlyOwner
|
||||
{
|
||||
_addAuthorizedAddress(target);
|
||||
}
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target) external override onlyOwner {
|
||||
function removeAuthorizedAddress(address target)
|
||||
external
|
||||
override
|
||||
onlyOwner
|
||||
{
|
||||
if (!authorized[target]) {
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.TargetNotAuthorizedError(target));
|
||||
}
|
||||
@@ -66,18 +82,33 @@ contract AuthorizableV06 is OwnableV06, IAuthorizableV06 {
|
||||
/// @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 override onlyOwner {
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external
|
||||
override
|
||||
onlyOwner
|
||||
{
|
||||
_removeAuthorizedAddressAtIndex(target, index);
|
||||
}
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses() external view override returns (address[] memory) {
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
override
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
return authorities;
|
||||
}
|
||||
|
||||
/// @dev Reverts if msg.sender is not authorized.
|
||||
function _assertSenderIsAuthorized() internal view {
|
||||
function _assertSenderIsAuthorized()
|
||||
internal
|
||||
view
|
||||
{
|
||||
if (!authorized[msg.sender]) {
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.SenderNotAuthorizedError(msg.sender));
|
||||
}
|
||||
@@ -85,7 +116,9 @@ contract AuthorizableV06 is OwnableV06, IAuthorizableV06 {
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function _addAuthorizedAddress(address target) internal {
|
||||
function _addAuthorizedAddress(address target)
|
||||
internal
|
||||
{
|
||||
// Ensure that the target is not the zero address.
|
||||
if (target == address(0)) {
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.ZeroCantBeAuthorizedError());
|
||||
@@ -104,17 +137,26 @@ contract AuthorizableV06 is OwnableV06, IAuthorizableV06 {
|
||||
/// @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) internal {
|
||||
function _removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
{
|
||||
if (!authorized[target]) {
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.TargetNotAuthorizedError(target));
|
||||
}
|
||||
if (index >= authorities.length) {
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.IndexOutOfBoundsError(index, authorities.length));
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.IndexOutOfBoundsError(
|
||||
index,
|
||||
authorities.length
|
||||
));
|
||||
}
|
||||
if (authorities[index] != target) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibAuthorizableRichErrorsV06.AuthorizedAddressMismatchError(authorities[index], target)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.AuthorizedAddressMismatchError(
|
||||
authorities[index],
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
delete authorized[target];
|
||||
|
@@ -22,7 +22,9 @@ pragma solidity ^0.6.5;
|
||||
import "./errors/LibBytesRichErrorsV06.sol";
|
||||
import "./errors/LibRichErrorsV06.sol";
|
||||
|
||||
|
||||
library LibBytesV06 {
|
||||
|
||||
using LibBytesV06 for bytes;
|
||||
|
||||
/// @dev Gets the memory address for a byte array.
|
||||
@@ -30,7 +32,11 @@ library LibBytesV06 {
|
||||
/// @return memoryAddress Memory address of byte array. This
|
||||
/// points to the header of the byte array which contains
|
||||
/// the length.
|
||||
function rawAddress(bytes memory input) internal pure returns (uint256 memoryAddress) {
|
||||
function rawAddress(bytes memory input)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 memoryAddress)
|
||||
{
|
||||
assembly {
|
||||
memoryAddress := input
|
||||
}
|
||||
@@ -40,7 +46,11 @@ library LibBytesV06 {
|
||||
/// @dev Gets the memory address for the contents of a byte array.
|
||||
/// @param input Byte array to lookup.
|
||||
/// @return memoryAddress Memory address of the contents of the byte array.
|
||||
function contentAddress(bytes memory input) internal pure returns (uint256 memoryAddress) {
|
||||
function contentAddress(bytes memory input)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 memoryAddress)
|
||||
{
|
||||
assembly {
|
||||
memoryAddress := add(input, 32)
|
||||
}
|
||||
@@ -51,7 +61,14 @@ library LibBytesV06 {
|
||||
/// @param dest memory address to copy bytes to.
|
||||
/// @param source memory address to copy bytes from.
|
||||
/// @param length number of bytes to copy.
|
||||
function memCopy(uint256 dest, uint256 source, uint256 length) internal pure {
|
||||
function memCopy(
|
||||
uint256 dest,
|
||||
uint256 source,
|
||||
uint256 length
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (length < 32) {
|
||||
// Handle a partial word by reading destination and masking
|
||||
// off the bits we are interested in.
|
||||
@@ -102,11 +119,8 @@ library LibBytesV06 {
|
||||
// Copy whole words front to back
|
||||
// Note: the first check is always true,
|
||||
// this could have been a do-while loop.
|
||||
for {
|
||||
|
||||
} lt(source, sEnd) {
|
||||
|
||||
} {
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
for {} lt(source, sEnd) {} {
|
||||
mstore(dest, mload(source))
|
||||
source := add(source, 32)
|
||||
dest := add(dest, 32)
|
||||
@@ -136,11 +150,8 @@ library LibBytesV06 {
|
||||
// 2**255, so they can be safely re-interpreted as signed.
|
||||
// Note: the first check is always true,
|
||||
// this could have been a do-while loop.
|
||||
for {
|
||||
|
||||
} slt(dest, dEnd) {
|
||||
|
||||
} {
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
for {} slt(dest, dEnd) {} {
|
||||
mstore(dEnd, mload(sEnd))
|
||||
sEnd := sub(sEnd, 32)
|
||||
dEnd := sub(dEnd, 32)
|
||||
@@ -158,31 +169,39 @@ library LibBytesV06 {
|
||||
/// @param from The starting index for the slice (inclusive).
|
||||
/// @param to The final index for the slice (exclusive).
|
||||
/// @return result The slice containing bytes at indices [from, to)
|
||||
function slice(bytes memory b, uint256 from, uint256 to) internal pure returns (bytes memory result) {
|
||||
function slice(
|
||||
bytes memory b,
|
||||
uint256 from,
|
||||
uint256 to
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory result)
|
||||
{
|
||||
// Ensure that the from and to positions are valid positions for a slice within
|
||||
// the byte array that is being used.
|
||||
if (from > to) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
));
|
||||
}
|
||||
if (to > b.length) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
));
|
||||
}
|
||||
|
||||
// Create a new bytes structure and copy contents
|
||||
result = new bytes(to - from);
|
||||
memCopy(result.contentAddress(), b.contentAddress() + from, result.length);
|
||||
memCopy(
|
||||
result.contentAddress(),
|
||||
b.contentAddress() + from,
|
||||
result.length
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -193,26 +212,30 @@ library LibBytesV06 {
|
||||
/// @param from The starting index for the slice (inclusive).
|
||||
/// @param to The final index for the slice (exclusive).
|
||||
/// @return result The slice containing bytes at indices [from, to)
|
||||
function sliceDestructive(bytes memory b, uint256 from, uint256 to) internal pure returns (bytes memory result) {
|
||||
function sliceDestructive(
|
||||
bytes memory b,
|
||||
uint256 from,
|
||||
uint256 to
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory result)
|
||||
{
|
||||
// Ensure that the from and to positions are valid positions for a slice within
|
||||
// the byte array that is being used.
|
||||
if (from > to) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.FromLessThanOrEqualsToRequired,
|
||||
from,
|
||||
to
|
||||
));
|
||||
}
|
||||
if (to > b.length) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.ToLessThanOrEqualsLengthRequired,
|
||||
to,
|
||||
b.length
|
||||
));
|
||||
}
|
||||
|
||||
// Create a new bytes structure around [from, to) in-place.
|
||||
@@ -226,15 +249,17 @@ library LibBytesV06 {
|
||||
/// @dev Pops the last byte off of a byte array by modifying its length.
|
||||
/// @param b Byte array that will be modified.
|
||||
/// @return result The byte that was popped off.
|
||||
function popLastByte(bytes memory b) internal pure returns (bytes1 result) {
|
||||
function popLastByte(bytes memory b)
|
||||
internal
|
||||
pure
|
||||
returns (bytes1 result)
|
||||
{
|
||||
if (b.length == 0) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanZeroRequired,
|
||||
b.length,
|
||||
0
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanZeroRequired,
|
||||
b.length,
|
||||
0
|
||||
));
|
||||
}
|
||||
|
||||
// Store last byte.
|
||||
@@ -252,7 +277,14 @@ library LibBytesV06 {
|
||||
/// @param lhs First byte array to compare.
|
||||
/// @param rhs Second byte array to compare.
|
||||
/// @return equal True if arrays are the same. False otherwise.
|
||||
function equals(bytes memory lhs, bytes memory rhs) internal pure returns (bool equal) {
|
||||
function equals(
|
||||
bytes memory lhs,
|
||||
bytes memory rhs
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool equal)
|
||||
{
|
||||
// Keccak gas cost is 30 + numWords * 6. This is a cheap way to compare.
|
||||
// We early exit on unequal lengths, but keccak would also correctly
|
||||
// handle this.
|
||||
@@ -263,15 +295,20 @@ library LibBytesV06 {
|
||||
/// @param b Byte array containing an address.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @return result address from byte array.
|
||||
function readAddress(bytes memory b, uint256 index) internal pure returns (address result) {
|
||||
function readAddress(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (address result)
|
||||
{
|
||||
if (b.length < index + 20) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
));
|
||||
}
|
||||
|
||||
// Add offset to index:
|
||||
@@ -293,15 +330,20 @@ library LibBytesV06 {
|
||||
/// @param b Byte array to insert address into.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @param input Address to put into byte array.
|
||||
function writeAddress(bytes memory b, uint256 index, address input) internal pure {
|
||||
function writeAddress(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
address input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (b.length < index + 20) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired,
|
||||
b.length,
|
||||
index + 20 // 20 is length of address
|
||||
));
|
||||
}
|
||||
|
||||
// Add offset to index:
|
||||
@@ -337,15 +379,20 @@ library LibBytesV06 {
|
||||
/// @param b Byte array containing a bytes32 value.
|
||||
/// @param index Index in byte array of bytes32 value.
|
||||
/// @return result bytes32 value from byte array.
|
||||
function readBytes32(bytes memory b, uint256 index) internal pure returns (bytes32 result) {
|
||||
function readBytes32(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
if (b.length < index + 32) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
@@ -362,15 +409,20 @@ library LibBytesV06 {
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input bytes32 to put into byte array.
|
||||
function writeBytes32(bytes memory b, uint256 index, bytes32 input) internal pure {
|
||||
function writeBytes32(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
bytes32 input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
if (b.length < index + 32) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired,
|
||||
b.length,
|
||||
index + 32
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
@@ -386,7 +438,14 @@ library LibBytesV06 {
|
||||
/// @param b Byte array containing a uint256 value.
|
||||
/// @param index Index in byte array of uint256 value.
|
||||
/// @return result uint256 value from byte array.
|
||||
function readUint256(bytes memory b, uint256 index) internal pure returns (uint256 result) {
|
||||
function readUint256(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 result)
|
||||
{
|
||||
result = uint256(readBytes32(b, index));
|
||||
return result;
|
||||
}
|
||||
@@ -395,7 +454,14 @@ library LibBytesV06 {
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input uint256 to put into byte array.
|
||||
function writeUint256(bytes memory b, uint256 index, uint256 input) internal pure {
|
||||
function writeUint256(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
uint256 input
|
||||
)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
writeBytes32(b, index, bytes32(input));
|
||||
}
|
||||
|
||||
@@ -403,15 +469,20 @@ library LibBytesV06 {
|
||||
/// @param b Byte array containing a bytes4 value.
|
||||
/// @param index Index in byte array of bytes4 value.
|
||||
/// @return result bytes4 value from byte array.
|
||||
function readBytes4(bytes memory b, uint256 index) internal pure returns (bytes4 result) {
|
||||
function readBytes4(
|
||||
bytes memory b,
|
||||
uint256 index
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes4 result)
|
||||
{
|
||||
if (b.length < index + 4) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsFourRequired,
|
||||
b.length,
|
||||
index + 4
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibBytesRichErrorsV06.InvalidByteOperationError(
|
||||
LibBytesRichErrorsV06.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsFourRequired,
|
||||
b.length,
|
||||
index + 4
|
||||
));
|
||||
}
|
||||
|
||||
// Arrays are prefixed by a 32 byte length field
|
||||
@@ -432,7 +503,10 @@ library LibBytesV06 {
|
||||
/// Increasing length may lead to appending adjacent in-memory bytes to the end of the byte array.
|
||||
/// @param b Bytes array to write new length to.
|
||||
/// @param length New length of byte array.
|
||||
function writeLength(bytes memory b, uint256 length) internal pure {
|
||||
function writeLength(bytes memory b, uint256 length)
|
||||
internal
|
||||
pure
|
||||
{
|
||||
assembly {
|
||||
mstore(b, length)
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ import "./LibSafeMathV06.sol";
|
||||
import "./errors/LibRichErrorsV06.sol";
|
||||
import "./errors/LibMathRichErrorsV06.sol";
|
||||
|
||||
|
||||
library LibMathV06 {
|
||||
|
||||
using LibSafeMathV06 for uint256;
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
@@ -36,9 +38,21 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
if (isRoundingErrorFloor(numerator, denominator, target)) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(numerator, denominator, target));
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
@@ -55,15 +69,29 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
if (isRoundingErrorCeil(numerator, denominator, target)) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(numerator, denominator, target));
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
// 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 = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -77,7 +105,11 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -91,11 +123,17 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (uint256 partialAmount) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
// 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 = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
@@ -109,7 +147,11 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (bool isError) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.DivisionByZeroError());
|
||||
}
|
||||
@@ -140,7 +182,11 @@ library LibMathV06 {
|
||||
// 1000 * remainder < numerator * target
|
||||
// so we have a rounding error iff:
|
||||
// 1000 * remainder >= numerator * target
|
||||
uint256 remainder = mulmod(target, numerator, denominator);
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
}
|
||||
@@ -154,7 +200,11 @@ library LibMathV06 {
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
) internal pure returns (bool isError) {
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.DivisionByZeroError());
|
||||
}
|
||||
@@ -167,7 +217,11 @@ library LibMathV06 {
|
||||
return false;
|
||||
}
|
||||
// Compute remainder as before
|
||||
uint256 remainder = mulmod(target, numerator, denominator);
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
remainder = denominator.safeSub(remainder) % denominator;
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
|
@@ -22,147 +22,183 @@ pragma solidity ^0.6.5;
|
||||
import "./errors/LibRichErrorsV06.sol";
|
||||
import "./errors/LibSafeMathRichErrorsV06.sol";
|
||||
|
||||
|
||||
library LibSafeMathV06 {
|
||||
function safeMul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
|
||||
function safeMul(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint256 c = a * b;
|
||||
if (c / a != b) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeDiv(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (b == 0) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
uint256 c = a / b;
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeSub(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
if (b > a) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function safeAdd(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
uint256 c = a + b;
|
||||
if (c < a) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function max256(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function max256(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return a >= b ? a : b;
|
||||
}
|
||||
|
||||
function min256(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function min256(uint256 a, uint256 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
function safeMul128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function safeMul128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint128 c = a * b;
|
||||
if (c / a != b) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeDiv128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function safeDiv128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
if (b == 0) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
uint128 c = a / b;
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeSub128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function safeSub128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
if (b > a) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function safeAdd128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function safeAdd128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
uint128 c = a + b;
|
||||
if (c < a) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||
a,
|
||||
b
|
||||
));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function max128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function max128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
return a >= b ? a : b;
|
||||
}
|
||||
|
||||
function min128(uint128 a, uint128 b) internal pure returns (uint128) {
|
||||
function min128(uint128 a, uint128 b)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
function safeDowncastToUint128(uint256 a) internal pure returns (uint128) {
|
||||
function safeDowncastToUint128(uint256 a)
|
||||
internal
|
||||
pure
|
||||
returns (uint128)
|
||||
{
|
||||
if (a > type(uint128).max) {
|
||||
LibRichErrorsV06.rrevert(
|
||||
LibSafeMathRichErrorsV06.Uint256DowncastError(
|
||||
LibSafeMathRichErrorsV06.DowncastErrorCodes.VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT128,
|
||||
a
|
||||
)
|
||||
);
|
||||
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256DowncastError(
|
||||
LibSafeMathRichErrorsV06.DowncastErrorCodes.VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT128,
|
||||
a
|
||||
));
|
||||
}
|
||||
return uint128(a);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user