Compare commits
1 Commits
developmen
...
david/reex
Author | SHA1 | Date | |
---|---|---|---|
|
6aad74a347 |
61
.github/workflows/ci.yml
vendored
61
.github/workflows/ci.yml
vendored
@ -83,30 +83,28 @@ jobs:
|
||||
-p @0x/order-utils \
|
||||
-m --serial -c test:ci
|
||||
|
||||
# NOTE: disabled as ZRXToken.sol did not compile with the latest forge.
|
||||
# TODO: re-enable once the issue is resolved.
|
||||
- name: Run Forge build for erc20
|
||||
working-directory: contracts/erc20
|
||||
run: |
|
||||
forge --version
|
||||
forge build --sizes --skip ZRXToken
|
||||
forge build --sizes
|
||||
|
||||
# - name: Run Forge tests for erc20
|
||||
# working-directory: contracts/erc20
|
||||
# run: |
|
||||
# forge test -vvv --gas-report
|
||||
- name: Run Forge tests for erc20
|
||||
working-directory: contracts/erc20
|
||||
run: |
|
||||
forge test -vvv --gas-report
|
||||
|
||||
# - name: Run Forge coverage for erc20
|
||||
# working-directory: contracts/erc20
|
||||
# run: |
|
||||
# forge coverage --report summary --report lcov
|
||||
- name: Run Forge coverage for erc20
|
||||
working-directory: contracts/erc20
|
||||
run: |
|
||||
forge coverage --report summary --report lcov
|
||||
|
||||
# - name: Upload the coverage report to Coveralls
|
||||
# uses: coverallsapp/github-action@master
|
||||
# with:
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# base-path: ./contracts/erc20/
|
||||
# path-to-lcov: ./contracts/erc20/lcov.info
|
||||
- name: Upload the coverage report to Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
base-path: ./contracts/erc20/
|
||||
path-to-lcov: ./contracts/erc20/lcov.info
|
||||
|
||||
- name: Run Forge build for zero-ex
|
||||
working-directory: contracts/zero-ex
|
||||
@ -144,20 +142,19 @@ jobs:
|
||||
forge --version
|
||||
forge build --sizes
|
||||
|
||||
# TODO: re-enable once the issue is resolved.
|
||||
# - name: Run Forge tests on governance contracts
|
||||
# working-directory: ./contracts/governance
|
||||
# run: |
|
||||
# forge test -vvv --gas-report
|
||||
- name: Run Forge tests on governance contracts
|
||||
working-directory: ./contracts/governance
|
||||
run: |
|
||||
forge test -vvv --gas-report
|
||||
|
||||
# - name: Run Forge coverage on governance contracts
|
||||
# working-directory: ./contracts/governance
|
||||
# run: |
|
||||
# forge coverage --report lcov
|
||||
- name: Run Forge coverage on governance contracts
|
||||
working-directory: ./contracts/governance
|
||||
run: |
|
||||
forge coverage --report lcov
|
||||
|
||||
# - name: Upload the coverage report to Coveralls
|
||||
# uses: coverallsapp/github-action@master
|
||||
# with:
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# base-path: ./contracts/governance/
|
||||
# path-to-lcov: ./contracts/governance/lcov.info
|
||||
- name: Upload the coverage report to Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
base-path: ./contracts/governance/
|
||||
path-to-lcov: ./contracts/governance/lcov.info
|
||||
|
54
.github/workflows/publish.yml
vendored
54
.github/workflows/publish.yml
vendored
@ -1,21 +1,19 @@
|
||||
name: publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ci_status:
|
||||
description: 'required CI status'
|
||||
default: 'success'
|
||||
required: true
|
||||
prerelease:
|
||||
description: 'prerelease name'
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ci_status:
|
||||
description: 'required CI status'
|
||||
default: 'success'
|
||||
required: true
|
||||
prerelease:
|
||||
description: 'prerelease name'
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PublishBranch: publish/${{github.ref_name }}-${{ github.run_id }}-${{ github.run_number }}
|
||||
steps:
|
||||
- name: 'check successful status'
|
||||
run: |
|
||||
@ -30,20 +28,16 @@ jobs:
|
||||
version: nightly
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref }}
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 16
|
||||
- uses: actions/setup-python@v2
|
||||
- name: 'configure git'
|
||||
run: |
|
||||
git config --global user.email "github-actions@github.com"
|
||||
git config --global user.name "Github Actions"
|
||||
- name: 'Checkout new branch'
|
||||
run: |
|
||||
git checkout -b $PublishBranch
|
||||
git push -u origin $PublishBranch
|
||||
- name: 'install dependencies'
|
||||
run: |
|
||||
yarn -D
|
||||
@ -55,23 +49,9 @@ jobs:
|
||||
NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
PUBLISH_PRERELEASE: ${{ github.event.inputs.prerelease }}
|
||||
- name: 'Create PR to merge into ref branch'
|
||||
- name: 'merge into main branch'
|
||||
if: github.event.inputs.prerelease == '' # unless it's a prerelease
|
||||
run: |
|
||||
gh pr create \
|
||||
-B ${{ github.ref_name }} \
|
||||
-H $PublishBranch \
|
||||
--title "Publish: CHANGELOG and Package Version Updates into ${{ github.ref_name }}" \
|
||||
--body "Syncing CHANGELOG and package version updates from publish action ${{github.run_id}}-${{github.run_number}} into ${{ github.ref_name}} branch" \
|
||||
--reviewer ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: 'Create PR to merge ref branch into main'
|
||||
run: |
|
||||
gh pr create \
|
||||
-B main \
|
||||
-H ${{ github.ref_name }} \
|
||||
--title "Publish: Sync ${{ github.ref_name }} into main " \
|
||||
--body "Syncing ${{ github.ref_name }} back into main after publish action. NOTE: this PR should be merged after CHANGELOG and package version updates have been merged into ${{ github.ref_name }}" \
|
||||
--reviewer ${{ github.actor }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
git checkout main && \
|
||||
git merge ${{ github.ref }} && \
|
||||
git push
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -84,9 +84,6 @@ TODO.md
|
||||
# IDE file
|
||||
.vscode
|
||||
.idea
|
||||
*~
|
||||
.\#*
|
||||
\#*\#
|
||||
|
||||
# generated contract artifacts/
|
||||
generated-artifacts/
|
||||
@ -102,7 +99,6 @@ foundry-artifacts/
|
||||
|
||||
# foundry cache
|
||||
cache/
|
||||
foundry-cache/
|
||||
|
||||
#foundry output artifacts
|
||||
out/
|
||||
|
@ -1,103 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1700094997,
|
||||
"version": "4.0.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1693346928,
|
||||
"version": "4.0.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1692368658,
|
||||
"version": "4.0.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1691617396,
|
||||
"version": "4.0.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689974915,
|
||||
"version": "4.0.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689791426,
|
||||
"version": "4.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1683749017,
|
||||
"version": "4.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1682976338,
|
||||
"version": "4.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681969282,
|
||||
"version": "4.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1681756154
|
||||
},
|
||||
{
|
||||
"timestamp": 1681697326,
|
||||
"version": "4.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681157139,
|
||||
"version": "4.0.3",
|
||||
|
@ -5,50 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.0.14 - _November 16, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.13 - _August 29, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.12 - _August 18, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.11 - _August 9, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.10 - _July 21, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.9 - _July 19, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.8 - _May 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.7 - _May 1, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.6 - _April 20, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.5 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.4 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.0.3 - _April 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c
|
||||
Subproject commit a2edd39db95df7e9dd3f9ef9edc8c55fefddb6df
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc20",
|
||||
"version": "4.0.14",
|
||||
"version": "4.0.3",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol",
|
||||
"devDependencies": {
|
||||
"@0x/contracts-utils": "^4.8.52",
|
||||
"@0x/contracts-utils": "^4.8.41",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"typedoc": "~0.16.11"
|
||||
},
|
||||
|
@ -39,6 +39,7 @@ contract WETH9V06Test is Test {
|
||||
function testShouldConvertDepositedETHToWrappedETH() public {
|
||||
vm.prank(user);
|
||||
etherToken.deposit{value: 1e20}();
|
||||
vm.stopPrank();
|
||||
|
||||
assertEq(etherToken.balanceOf(user), 1e20);
|
||||
assertEq(address(etherToken).balance, 1e20);
|
||||
@ -57,6 +58,7 @@ contract WETH9V06Test is Test {
|
||||
etherToken.deposit{value: 1e20}();
|
||||
vm.prank(user);
|
||||
etherToken.withdraw(100);
|
||||
vm.stopPrank();
|
||||
|
||||
assertEq(etherToken.balanceOf(user), 1e20 - 100);
|
||||
assertEq(address(etherToken).balance, 1e20 - 100);
|
||||
@ -66,6 +68,7 @@ contract WETH9V06Test is Test {
|
||||
function testShouldConvertSentETHToWrappedETH() public {
|
||||
vm.prank(user);
|
||||
address(etherToken).call{value: 1e20}(new bytes(0));
|
||||
vm.stopPrank();
|
||||
|
||||
assertEq(etherToken.balanceOf(user), 1e20);
|
||||
assertEq(address(etherToken).balance, 1e20);
|
||||
|
@ -34,6 +34,7 @@ contract ZRXTokenTest is Test {
|
||||
assembly {
|
||||
_address := create(0, add(_bytecode, 0x20), mload(_bytecode))
|
||||
}
|
||||
vm.stopPrank();
|
||||
zrxToken = IERC20Token(address(_address));
|
||||
}
|
||||
|
||||
@ -72,6 +73,7 @@ contract ZRXTokenTest is Test {
|
||||
function testShouldReturnFalseIfSenderHasInsufficientBalance() public {
|
||||
vm.prank(owner);
|
||||
zrxToken.approve(user, totalSupply + 1);
|
||||
vm.stopPrank();
|
||||
|
||||
bool success = zrxToken.transferFrom(owner, user, totalSupply + 1);
|
||||
assertEq(success, false);
|
||||
@ -80,6 +82,7 @@ contract ZRXTokenTest is Test {
|
||||
function testShouldReturnFalseIfRecipientHasInsufficientAllowance() public {
|
||||
vm.prank(owner);
|
||||
zrxToken.approve(user, totalSupply - 1);
|
||||
vm.stopPrank();
|
||||
|
||||
bool success = zrxToken.transferFrom(owner, user, totalSupply);
|
||||
assertEq(success, false);
|
||||
@ -94,6 +97,7 @@ contract ZRXTokenTest is Test {
|
||||
function testShouldNotModifySenderAllowanceIfSetToUINT256Max() public {
|
||||
vm.prank(owner);
|
||||
zrxToken.approve(user, type(uint256).max);
|
||||
vm.stopPrank();
|
||||
|
||||
zrxToken.transferFrom(owner, user, 100);
|
||||
assertEq(zrxToken.allowance(owner, user), type(uint256).max);
|
||||
@ -102,6 +106,7 @@ contract ZRXTokenTest is Test {
|
||||
function testShouldTransferCorrectlyWhenSufficientAllowance() public {
|
||||
vm.prank(owner);
|
||||
zrxToken.approve(user, 1000 * 1e18);
|
||||
vm.stopPrank();
|
||||
|
||||
vm.prank(user);
|
||||
zrxToken.transferFrom(owner, user, 100 * 1e18);
|
||||
|
@ -1,40 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1682976338,
|
||||
"version": "1.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681756154,
|
||||
"version": "1.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681694690,
|
||||
"version": "1.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681687842,
|
||||
"version": "1.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681157139,
|
||||
"version": "1.0.1",
|
||||
|
@ -5,22 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.5 - _May 1, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.4 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.3 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.2 - _April 16, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.1 - _April 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/governance",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.1",
|
||||
"description": "Governance implementation for the 0x protocol and treasury",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
@ -20,8 +20,5 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/protocol.git"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -154,6 +155,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -264,6 +266,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -327,6 +330,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -362,6 +366,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -397,6 +402,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
@ -432,6 +438,7 @@ abstract contract ZeroExGovernorBaseTest is BaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
|
@ -70,12 +70,13 @@ contract ZeroExProtocolGovernorTest is ZeroExGovernorBaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
|
||||
vm.stopPrank();
|
||||
vm.prank(account3);
|
||||
governor.castVote(proposalId, 0); // Vote "against"
|
||||
|
||||
vm.stopPrank();
|
||||
vm.prank(account4);
|
||||
governor.castVote(proposalId, 2); // Vote "abstain"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
|
@ -66,12 +66,13 @@ contract ZeroExTreasuryGovernorTest is ZeroExGovernorBaseTest {
|
||||
// Vote
|
||||
vm.prank(account2);
|
||||
governor.castVote(proposalId, 1); // Vote "for"
|
||||
|
||||
vm.stopPrank();
|
||||
vm.prank(account3);
|
||||
governor.castVote(proposalId, 0); // Vote "against"
|
||||
|
||||
vm.stopPrank();
|
||||
vm.prank(account4);
|
||||
governor.castVote(proposalId, 2); // Vote "abstain"
|
||||
vm.stopPrank();
|
||||
|
||||
// Fast forward to vote end
|
||||
vm.roll(governor.proposalDeadline(proposalId) + 1);
|
||||
|
@ -1,94 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1700094997,
|
||||
"version": "5.4.60",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1693346928,
|
||||
"version": "5.4.59",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1692368658,
|
||||
"version": "5.4.58",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1691617396,
|
||||
"version": "5.4.57",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689974915,
|
||||
"version": "5.4.56",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689791426,
|
||||
"version": "5.4.55",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1683749017,
|
||||
"version": "5.4.54",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1682976338,
|
||||
"version": "5.4.53",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681969282,
|
||||
"version": "5.4.52",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681697326,
|
||||
"version": "5.4.51",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "5.4.50",
|
||||
"changes": [
|
||||
|
@ -5,46 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.4.60 - _November 16, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.59 - _August 29, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.58 - _August 18, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.57 - _August 9, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.56 - _July 21, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.55 - _July 19, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.54 - _May 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.53 - _May 1, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.52 - _April 20, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.51 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.50 - _April 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-test-utils",
|
||||
"version": "5.4.60",
|
||||
"version": "5.4.50",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -41,7 +41,7 @@
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.36",
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/contract-addresses": "^8.13.0",
|
||||
"@0x/contract-addresses": "^8.2.0",
|
||||
"@0x/dev-utils": "^5.0.2",
|
||||
"@0x/json-schemas": "^6.4.4",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
|
@ -20,7 +20,6 @@ export { signingUtils } from './signing_utils';
|
||||
export { orderUtils } from './order_utils';
|
||||
export { typeEncodingUtils } from './type_encoding_utils';
|
||||
export { profiler } from './profiler';
|
||||
export { Web3ProviderEngine } from '@0x/subproviders';
|
||||
export { randomAddress } from './address_utils';
|
||||
export { OrderFactory } from './order_factory';
|
||||
export { bytes32Values, testCombinatoriallyWithReferenceFunc, uint256Values } from './combinatorial_utils';
|
||||
|
@ -1,103 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1700094997,
|
||||
"version": "1.4.54",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1693346928,
|
||||
"version": "1.4.53",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1692368658,
|
||||
"version": "1.4.52",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1691617396,
|
||||
"version": "1.4.51",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689974915,
|
||||
"version": "1.4.50",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689791426,
|
||||
"version": "1.4.49",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1683749017,
|
||||
"version": "1.4.48",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1682976338,
|
||||
"version": "1.4.47",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1682334742,
|
||||
"version": "1.4.46",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681969282,
|
||||
"version": "1.4.45",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681697326,
|
||||
"version": "1.4.44",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.4.43",
|
||||
"changes": [
|
||||
|
@ -5,50 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.4.54 - _November 16, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.53 - _August 29, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.52 - _August 18, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.51 - _August 9, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.50 - _July 21, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.49 - _July 19, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.48 - _May 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.47 - _May 1, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.46 - _April 24, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.45 - _April 20, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.44 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.4.43 - _April 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-treasury",
|
||||
"version": "1.4.54",
|
||||
"version": "1.4.43",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -46,12 +46,12 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.8.5",
|
||||
"@0x/contract-addresses": "^8.13.0",
|
||||
"@0x/contract-addresses": "^8.2.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.19",
|
||||
"@0x/contracts-erc20": "3.3.57",
|
||||
"@0x/contracts-gen": "^2.0.50",
|
||||
"@0x/contracts-staking": "^2.0.45",
|
||||
"@0x/contracts-test-utils": "^5.4.60",
|
||||
"@0x/contracts-test-utils": "^5.4.50",
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@types/isomorphic-fetch": "^0.0.35",
|
||||
@ -73,7 +73,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/protocol-utils": "^11.24.2",
|
||||
"@0x/protocol-utils": "^11.18.2",
|
||||
"@0x/subproviders": "^8.0.1",
|
||||
"@0x/types": "^3.3.7",
|
||||
"@0x/typescript-typings": "^5.3.1",
|
||||
|
@ -1,103 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1700094997,
|
||||
"version": "4.8.52",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1693346928,
|
||||
"version": "4.8.51",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1692368658,
|
||||
"version": "4.8.50",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1691617396,
|
||||
"version": "4.8.49",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689974915,
|
||||
"version": "4.8.48",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1689791426,
|
||||
"version": "4.8.47",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1683749017,
|
||||
"version": "4.8.46",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1682976338,
|
||||
"version": "4.8.45",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1681969282,
|
||||
"version": "4.8.44",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.8.43",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1681756154
|
||||
},
|
||||
{
|
||||
"timestamp": 1681697326,
|
||||
"version": "4.8.42",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.8.41",
|
||||
"changes": [
|
||||
|
@ -5,50 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.8.52 - _November 16, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.51 - _August 29, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.50 - _August 18, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.49 - _August 9, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.48 - _July 21, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.47 - _July 19, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.46 - _May 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.45 - _May 1, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.44 - _April 20, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.43 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.42 - _April 17, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.41 - _April 10, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-utils",
|
||||
"version": "4.8.52",
|
||||
"version": "4.8.41",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -45,7 +45,7 @@
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.8.5",
|
||||
"@0x/contracts-gen": "^2.0.50",
|
||||
"@0x/contracts-test-utils": "^5.4.60",
|
||||
"@0x/contracts-test-utils": "^5.4.50",
|
||||
"@0x/dev-utils": "^5.0.2",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
|
@ -3,12 +3,3 @@ export * from './wrappers';
|
||||
|
||||
import * as ReferenceFunctionsToExport from './reference_functions';
|
||||
export import ReferenceFunctions = ReferenceFunctionsToExport;
|
||||
|
||||
export {
|
||||
AuthorizableRevertErrors,
|
||||
LibAddressArrayRevertErrors,
|
||||
LibBytesRevertErrors,
|
||||
OwnableRevertErrors,
|
||||
ReentrancyGuardRevertErrors,
|
||||
SafeMathRevertErrors,
|
||||
} from '@0x/utils';
|
||||
|
@ -1,121 +1,4 @@
|
||||
[
|
||||
{
|
||||
"version": "0.49.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Allowlist Sepolia in AbstractBridgeAdapter"
|
||||
}
|
||||
],
|
||||
"timestamp": 1700094997
|
||||
},
|
||||
{
|
||||
"version": "0.48.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add VelodromeV2 support on Base"
|
||||
}
|
||||
],
|
||||
"timestamp": 1693346928
|
||||
},
|
||||
{
|
||||
"version": "0.47.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add MaverickV1 support on Ethereum, BSC, and Base"
|
||||
}
|
||||
],
|
||||
"timestamp": 1692368658
|
||||
},
|
||||
{
|
||||
"version": "0.46.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add VelodromeV2 support on Optimism"
|
||||
}
|
||||
],
|
||||
"timestamp": 1691617396
|
||||
},
|
||||
{
|
||||
"timestamp": 1689974915,
|
||||
"version": "0.45.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.45.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Remove Bancor V1 support"
|
||||
},
|
||||
{
|
||||
"note": "Remove Shell and MStable support"
|
||||
},
|
||||
{
|
||||
"note": "Add Base Mainnet and Goerli BridgeAdapters"
|
||||
},
|
||||
{
|
||||
"note": "Add Uniswap V3 support on Avalanche and BSC"
|
||||
}
|
||||
],
|
||||
"timestamp": 1689791426
|
||||
},
|
||||
{
|
||||
"version": "0.44.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add Trader Joe V2 MixIn to Arbitrum"
|
||||
}
|
||||
],
|
||||
"timestamp": 1683749017
|
||||
},
|
||||
{
|
||||
"version": "0.43.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add Trader Joe V2.1 Router Support for MixIn"
|
||||
}
|
||||
],
|
||||
"timestamp": 1682976338
|
||||
},
|
||||
{
|
||||
"timestamp": 1682334742,
|
||||
"version": "0.42.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.42.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add Trader Joe V2 support on Avalanche"
|
||||
}
|
||||
],
|
||||
"timestamp": 1681969282
|
||||
},
|
||||
{
|
||||
"version": "0.41.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add Barter support on Ethereum"
|
||||
}
|
||||
],
|
||||
"timestamp": 1681756154
|
||||
},
|
||||
{
|
||||
"version": "0.40.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add Barter support on Ethereum"
|
||||
}
|
||||
],
|
||||
"timestamp": 1681697326
|
||||
},
|
||||
{
|
||||
"version": "0.39.2",
|
||||
"changes": [
|
||||
|
@ -5,57 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.49.0 - _November 16, 2023_
|
||||
|
||||
* Allowlist Sepolia in AbstractBridgeAdapter
|
||||
|
||||
## v0.48.0 - _August 29, 2023_
|
||||
|
||||
* Add VelodromeV2 support on Base
|
||||
|
||||
## v0.47.0 - _August 18, 2023_
|
||||
|
||||
* Add MaverickV1 support on Ethereum, BSC, and Base
|
||||
|
||||
## v0.46.0 - _August 9, 2023_
|
||||
|
||||
* Add VelodromeV2 support on Optimism
|
||||
|
||||
## v0.45.1 - _July 21, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.45.0 - _July 19, 2023_
|
||||
|
||||
* Remove Bancor V1 support
|
||||
* Remove Shell and MStable support
|
||||
* Add Base Mainnet and Goerli BridgeAdapters
|
||||
* Add Uniswap V3 support on Avalanche and BSC
|
||||
|
||||
## v0.44.0 - _May 10, 2023_
|
||||
|
||||
* Add Trader Joe V2 MixIn to Arbitrum
|
||||
|
||||
## v0.43.0 - _May 1, 2023_
|
||||
|
||||
* Add Trader Joe V2.1 Router Support for MixIn
|
||||
|
||||
## v0.42.1 - _April 24, 2023_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.42.0 - _April 20, 2023_
|
||||
|
||||
* Add Trader Joe V2 support on Avalanche
|
||||
|
||||
## v0.41.0 - _April 17, 2023_
|
||||
|
||||
* Add Barter support on Ethereum
|
||||
|
||||
## v0.40.0 - _April 17, 2023_
|
||||
|
||||
* Add Barter support on Ethereum
|
||||
|
||||
## v0.39.2 - _April 10, 2023_
|
||||
|
||||
* Uprgade dependencies
|
||||
|
@ -31,7 +31,6 @@
|
||||
"./contracts/src/features/FundRecoveryFeature.sol",
|
||||
"./contracts/src/features/LiquidityProviderFeature.sol",
|
||||
"./contracts/src/features/MetaTransactionsFeature.sol",
|
||||
"./contracts/src/features/MetaTransactionsFeatureV2.sol",
|
||||
"./contracts/src/features/NativeOrdersFeature.sol",
|
||||
"./contracts/src/features/OtcOrdersFeature.sol",
|
||||
"./contracts/src/features/OwnableFeature.sol",
|
||||
@ -49,7 +48,6 @@
|
||||
"./contracts/src/features/interfaces/IFundRecoveryFeature.sol",
|
||||
"./contracts/src/features/interfaces/ILiquidityProviderFeature.sol",
|
||||
"./contracts/src/features/interfaces/IMetaTransactionsFeature.sol",
|
||||
"./contracts/src/features/interfaces/IMetaTransactionsFeatureV2.sol",
|
||||
"./contracts/src/features/interfaces/IMultiplexFeature.sol",
|
||||
"./contracts/src/features/interfaces/INativeOrdersEvents.sol",
|
||||
"./contracts/src/features/interfaces/INativeOrdersFeature.sol",
|
||||
@ -115,8 +113,6 @@
|
||||
"./contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/AvalancheBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/BSCBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/BaseBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/BaseGoerliBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/BridgeProtocols.sol",
|
||||
"./contracts/src/transformers/bridges/CeloBridgeAdapter.sol",
|
||||
"./contracts/src/transformers/bridges/EthereumBridgeAdapter.sol",
|
||||
@ -127,6 +123,7 @@
|
||||
"./contracts/src/transformers/bridges/mixins/MixinAaveV2.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinBalancer.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinBalancerV2Batch.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinBancor.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinBancorV3.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinCompound.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinCryptoCom.sol",
|
||||
@ -137,10 +134,12 @@
|
||||
"./contracts/src/transformers/bridges/mixins/MixinGMX.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinKyberDmm.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinLido.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinMStable.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinMakerPSM.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinMooniswap.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinNerve.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinPlatypus.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinShell.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinSolidly.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinSynthetix.sol",
|
||||
"./contracts/src/transformers/bridges/mixins/MixinUniswap.sol",
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c
|
||||
Subproject commit a2edd39db95df7e9dd3f9ef9edc8c55fefddb6df
|
@ -20,7 +20,6 @@ import "./features/interfaces/ISimpleFunctionRegistryFeature.sol";
|
||||
import "./features/interfaces/ITokenSpenderFeature.sol";
|
||||
import "./features/interfaces/ITransformERC20Feature.sol";
|
||||
import "./features/interfaces/IMetaTransactionsFeature.sol";
|
||||
import "./features/interfaces/IMetaTransactionsFeatureV2.sol";
|
||||
import "./features/interfaces/IUniswapFeature.sol";
|
||||
import "./features/interfaces/IUniswapV3Feature.sol";
|
||||
import "./features/interfaces/IPancakeSwapFeature.sol";
|
||||
@ -40,7 +39,6 @@ interface IZeroEx is
|
||||
ISimpleFunctionRegistryFeature,
|
||||
ITransformERC20Feature,
|
||||
IMetaTransactionsFeature,
|
||||
IMetaTransactionsFeatureV2,
|
||||
IUniswapFeature,
|
||||
IUniswapV3Feature,
|
||||
IPancakeSwapFeature,
|
||||
|
@ -1,616 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||
import "../errors/LibMetaTransactionsRichErrors.sol";
|
||||
import "../fixins/FixinCommon.sol";
|
||||
import "../fixins/FixinReentrancyGuard.sol";
|
||||
import "../fixins/FixinTokenSpender.sol";
|
||||
import "../fixins/FixinEIP712.sol";
|
||||
import "../migrations/LibMigrate.sol";
|
||||
import "../storage/LibMetaTransactionsV2Storage.sol";
|
||||
import "./interfaces/IFeature.sol";
|
||||
import "./interfaces/IMetaTransactionsFeatureV2.sol";
|
||||
import "./interfaces/IMultiplexFeature.sol";
|
||||
import "./interfaces/INativeOrdersFeature.sol";
|
||||
import "./interfaces/ITransformERC20Feature.sol";
|
||||
import "./libs/LibSignature.sol";
|
||||
|
||||
/// @dev MetaTransactions feature.
|
||||
contract MetaTransactionsFeatureV2 is
|
||||
IFeature,
|
||||
IMetaTransactionsFeatureV2,
|
||||
FixinCommon,
|
||||
FixinReentrancyGuard,
|
||||
FixinEIP712,
|
||||
FixinTokenSpender
|
||||
{
|
||||
using LibBytesV06 for bytes;
|
||||
using LibRichErrorsV06 for bytes;
|
||||
|
||||
/// @dev Describes the state of a meta transaction.
|
||||
struct ExecuteState {
|
||||
// Sender of the meta-transaction.
|
||||
address sender;
|
||||
// Hash of the meta-transaction data.
|
||||
bytes32 hash;
|
||||
// The meta-transaction data.
|
||||
MetaTransactionDataV2 mtx;
|
||||
// The meta-transaction signature (by `mtx.signer`).
|
||||
LibSignature.Signature signature;
|
||||
// The selector of the function being called.
|
||||
bytes4 selector;
|
||||
// The ETH balance of this contract before performing the call.
|
||||
uint256 selfBalance;
|
||||
// The block number at which the meta-transaction was executed.
|
||||
uint256 executedBlockNumber;
|
||||
}
|
||||
|
||||
/// @dev Arguments for a `TransformERC20.transformERC20()` call.
|
||||
struct ExternalTransformERC20Args {
|
||||
IERC20Token inputToken;
|
||||
IERC20Token outputToken;
|
||||
uint256 inputTokenAmount;
|
||||
uint256 minOutputTokenAmount;
|
||||
ITransformERC20Feature.Transformation[] transformations;
|
||||
}
|
||||
|
||||
/// @dev Name of this feature.
|
||||
string public constant override FEATURE_NAME = "MetaTransactionsV2";
|
||||
/// @dev Version of this feature.
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||
/// @dev EIP712 typehash of the `MetaTransactionData` struct.
|
||||
bytes32 public immutable MTX_EIP712_TYPEHASH =
|
||||
keccak256(
|
||||
"MetaTransactionDataV2("
|
||||
"address signer,"
|
||||
"address sender,"
|
||||
"uint256 expirationTimeSeconds,"
|
||||
"uint256 salt,"
|
||||
"bytes callData,"
|
||||
"address feeToken,"
|
||||
"MetaTransactionFeeData[] fees"
|
||||
")"
|
||||
"MetaTransactionFeeData("
|
||||
"address recipient,"
|
||||
"uint256 amount"
|
||||
")"
|
||||
);
|
||||
bytes32 public immutable MTX_FEE_TYPEHASH =
|
||||
keccak256(
|
||||
"MetaTransactionFeeData("
|
||||
"address recipient,"
|
||||
"uint256 amount"
|
||||
")"
|
||||
);
|
||||
|
||||
/// @dev The WETH token contract.
|
||||
IEtherToken private immutable WETH;
|
||||
|
||||
/// @dev Ensures that the ETH balance of `this` does not go below the
|
||||
/// initial ETH balance before the call (excluding ETH attached to the call).
|
||||
modifier doesNotReduceEthBalance() {
|
||||
uint256 initialBalance = address(this).balance;
|
||||
_;
|
||||
require(initialBalance <= address(this).balance, "MetaTransactionsFeatureV2/ETH_LEAK");
|
||||
}
|
||||
|
||||
constructor(address zeroExAddress, IEtherToken weth) public FixinCommon() FixinEIP712(zeroExAddress) {
|
||||
WETH = weth;
|
||||
}
|
||||
|
||||
/// @dev Initialize and register this feature.
|
||||
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||
/// @return success `LibMigrate.SUCCESS` on success.
|
||||
function migrate() external returns (bytes4 success) {
|
||||
_registerFeatureFunction(this.executeMetaTransactionV2.selector);
|
||||
_registerFeatureFunction(this.batchExecuteMetaTransactionsV2.selector);
|
||||
_registerFeatureFunction(this.getMetaTransactionV2ExecutedBlock.selector);
|
||||
_registerFeatureFunction(this.getMetaTransactionV2HashExecutedBlock.selector);
|
||||
_registerFeatureFunction(this.getMetaTransactionV2Hash.selector);
|
||||
return LibMigrate.MIGRATE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev Execute a single meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @param signature The signature by `mtx.signer`.
|
||||
/// @return returnResult The ABI-encoded result of the underlying call.
|
||||
function executeMetaTransactionV2(
|
||||
MetaTransactionDataV2 memory mtx,
|
||||
LibSignature.Signature memory signature
|
||||
) public override nonReentrant(REENTRANCY_MTX) doesNotReduceEthBalance returns (bytes memory returnResult) {
|
||||
ExecuteState memory state;
|
||||
state.sender = msg.sender;
|
||||
state.mtx = mtx;
|
||||
state.hash = getMetaTransactionV2Hash(mtx);
|
||||
state.signature = signature;
|
||||
|
||||
returnResult = _executeMetaTransactionPrivate(state);
|
||||
}
|
||||
|
||||
/// @dev Execute multiple meta-transactions.
|
||||
/// @param mtxs The meta-transactions.
|
||||
/// @param signatures The signature by each respective `mtx.signer`.
|
||||
/// @return returnResults The ABI-encoded results of the underlying calls.
|
||||
function batchExecuteMetaTransactionsV2(
|
||||
MetaTransactionDataV2[] memory mtxs,
|
||||
LibSignature.Signature[] memory signatures
|
||||
) public override nonReentrant(REENTRANCY_MTX) doesNotReduceEthBalance returns (bytes[] memory returnResults) {
|
||||
if (mtxs.length != signatures.length) {
|
||||
LibMetaTransactionsRichErrors
|
||||
.InvalidMetaTransactionsArrayLengthsError(mtxs.length, signatures.length)
|
||||
.rrevert();
|
||||
}
|
||||
returnResults = new bytes[](mtxs.length);
|
||||
for (uint256 i = 0; i < mtxs.length; ++i) {
|
||||
ExecuteState memory state;
|
||||
state.sender = msg.sender;
|
||||
state.mtx = mtxs[i];
|
||||
state.hash = getMetaTransactionV2Hash(mtxs[i]);
|
||||
state.signature = signatures[i];
|
||||
|
||||
returnResults[i] = _executeMetaTransactionPrivate(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Get the block at which a meta-transaction has been executed.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionV2ExecutedBlock(
|
||||
MetaTransactionDataV2 memory mtx
|
||||
) public view override returns (uint256 blockNumber) {
|
||||
return getMetaTransactionV2HashExecutedBlock(getMetaTransactionV2Hash(mtx));
|
||||
}
|
||||
|
||||
/// @dev Get the block at which a meta-transaction hash has been executed.
|
||||
/// @param mtxHash The meta-transaction hash.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionV2HashExecutedBlock(bytes32 mtxHash) public view override returns (uint256 blockNumber) {
|
||||
return LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[mtxHash];
|
||||
}
|
||||
|
||||
/// @dev Get the EIP712 hash of a meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return mtxHash The EIP712 hash of `mtx`.
|
||||
function getMetaTransactionV2Hash(MetaTransactionDataV2 memory mtx) public view override returns (bytes32 mtxHash) {
|
||||
bytes32[] memory feeHashes = new bytes32[](mtx.fees.length);
|
||||
for (uint256 i = 0; i < mtx.fees.length; ++i) {
|
||||
feeHashes[i] = keccak256(abi.encode(MTX_FEE_TYPEHASH, mtx.fees[i]));
|
||||
}
|
||||
|
||||
return
|
||||
_getEIP712Hash(
|
||||
keccak256(
|
||||
abi.encode(
|
||||
MTX_EIP712_TYPEHASH,
|
||||
mtx.signer,
|
||||
mtx.sender,
|
||||
mtx.expirationTimeSeconds,
|
||||
mtx.salt,
|
||||
keccak256(mtx.callData),
|
||||
mtx.feeToken,
|
||||
keccak256(abi.encodePacked(feeHashes))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a meta-transaction by `sender`. Low-level, hidden variant.
|
||||
/// @param state The `ExecuteState` for this metatransaction, with `sender`,
|
||||
/// `hash`, `mtx`, and `signature` fields filled.
|
||||
/// @return returnResult The ABI-encoded result of the underlying call.
|
||||
function _executeMetaTransactionPrivate(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||
_validateMetaTransaction(state);
|
||||
|
||||
// Mark the transaction executed by storing the block at which it was executed.
|
||||
// Currently the block number just indicates that the mtx was executed and
|
||||
// serves no other purpose from within this contract.
|
||||
LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[state.hash] = block.number;
|
||||
|
||||
// Pay the fees to the fee recipients.
|
||||
for (uint256 i = 0; i < state.mtx.fees.length; ++i) {
|
||||
_transferERC20TokensFrom(
|
||||
state.mtx.feeToken,
|
||||
state.mtx.signer,
|
||||
state.mtx.fees[i].recipient,
|
||||
state.mtx.fees[i].amount
|
||||
);
|
||||
}
|
||||
|
||||
// Execute the call based on the selector.
|
||||
state.selector = state.mtx.callData.readBytes4(0);
|
||||
if (state.selector == ITransformERC20Feature.transformERC20.selector) {
|
||||
returnResult = _executeTransformERC20Call(state);
|
||||
} else if (state.selector == INativeOrdersFeature.fillLimitOrder.selector) {
|
||||
returnResult = _executeFillLimitOrderCall(state);
|
||||
} else if (state.selector == INativeOrdersFeature.fillRfqOrder.selector) {
|
||||
returnResult = _executeFillRfqOrderCall(state);
|
||||
} else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForToken.selector) {
|
||||
returnResult = _executeMultiplexBatchSellTokenForTokenCall(state);
|
||||
} else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForEth.selector) {
|
||||
returnResult = _executeMultiplexBatchSellTokenForEthCall(state);
|
||||
} else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForToken.selector) {
|
||||
returnResult = _executeMultiplexMultiHopSellTokenForTokenCall(state);
|
||||
} else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForEth.selector) {
|
||||
returnResult = _executeMultiplexMultiHopSellTokenForEthCall(state);
|
||||
} else {
|
||||
LibMetaTransactionsRichErrors.MetaTransactionUnsupportedFunctionError(state.hash, state.selector).rrevert();
|
||||
}
|
||||
emit MetaTransactionExecuted(state.hash, state.selector, state.mtx.signer, state.mtx.sender);
|
||||
}
|
||||
|
||||
/// @dev Validate that a meta-transaction is executable.
|
||||
function _validateMetaTransaction(ExecuteState memory state) private view {
|
||||
// Must be from the required sender, if set.
|
||||
if (state.mtx.sender != address(0) && state.mtx.sender != state.sender) {
|
||||
LibMetaTransactionsRichErrors
|
||||
.MetaTransactionWrongSenderError(state.hash, state.sender, state.mtx.sender)
|
||||
.rrevert();
|
||||
}
|
||||
// Must not be expired.
|
||||
if (state.mtx.expirationTimeSeconds <= block.timestamp) {
|
||||
LibMetaTransactionsRichErrors
|
||||
.MetaTransactionExpiredError(state.hash, block.timestamp, state.mtx.expirationTimeSeconds)
|
||||
.rrevert();
|
||||
}
|
||||
|
||||
if (LibSignature.getSignerOfHash(state.hash, state.signature) != state.mtx.signer) {
|
||||
LibSignatureRichErrors
|
||||
.SignatureValidationError(
|
||||
LibSignatureRichErrors.SignatureValidationErrorCodes.WRONG_SIGNER,
|
||||
state.hash,
|
||||
state.mtx.signer,
|
||||
// TODO: Remove this field from SignatureValidationError
|
||||
// when rich reverts are part of the protocol repo.
|
||||
""
|
||||
)
|
||||
.rrevert();
|
||||
}
|
||||
// Transaction must not have been already executed.
|
||||
state.executedBlockNumber = LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[state.hash];
|
||||
if (state.executedBlockNumber != 0) {
|
||||
LibMetaTransactionsRichErrors
|
||||
.MetaTransactionAlreadyExecutedError(state.hash, state.executedBlockNumber)
|
||||
.rrevert();
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Execute a `ITransformERC20Feature.transformERC20()` meta-transaction call
|
||||
/// by decoding the call args and translating the call to the internal
|
||||
/// `ITransformERC20Feature._transformERC20()` variant, where we can override
|
||||
/// the taker address.
|
||||
function _executeTransformERC20Call(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||
// HACK(dorothy-zbornak): `abi.decode()` with the individual args
|
||||
// will cause a stack overflow. But we can prefix the call data with an
|
||||
// offset to transform it into the encoding for the equivalent single struct arg,
|
||||
// since decoding a single struct arg consumes far less stack space than
|
||||
// decoding multiple struct args.
|
||||
|
||||
// Where the encoding for multiple args (with the selector ommitted)
|
||||
// would typically look like:
|
||||
// | argument | offset |
|
||||
// |--------------------------|---------|
|
||||
// | inputToken | 0 |
|
||||
// | outputToken | 32 |
|
||||
// | inputTokenAmount | 64 |
|
||||
// | minOutputTokenAmount | 96 |
|
||||
// | transformations (offset) | 128 | = 32
|
||||
// | transformations (data) | 160 |
|
||||
|
||||
// We will ABI-decode a single struct arg copy with the layout:
|
||||
// | argument | offset |
|
||||
// |--------------------------|---------|
|
||||
// | (arg 1 offset) | 0 | = 32
|
||||
// | inputToken | 32 |
|
||||
// | outputToken | 64 |
|
||||
// | inputTokenAmount | 96 |
|
||||
// | minOutputTokenAmount | 128 |
|
||||
// | transformations (offset) | 160 | = 32
|
||||
// | transformations (data) | 192 |
|
||||
|
||||
ExternalTransformERC20Args memory args;
|
||||
{
|
||||
bytes memory encodedStructArgs = new bytes(state.mtx.callData.length - 4 + 32);
|
||||
// Copy the args data from the original, after the new struct offset prefix.
|
||||
bytes memory fromCallData = state.mtx.callData;
|
||||
assert(fromCallData.length >= 160);
|
||||
uint256 fromMem;
|
||||
uint256 toMem;
|
||||
assembly {
|
||||
// Prefix the calldata with a struct offset,
|
||||
// which points to just one word over.
|
||||
mstore(add(encodedStructArgs, 32), 32)
|
||||
// Copy everything after the selector.
|
||||
fromMem := add(fromCallData, 36)
|
||||
// Start copying after the struct offset.
|
||||
toMem := add(encodedStructArgs, 64)
|
||||
}
|
||||
LibBytesV06.memCopy(toMem, fromMem, fromCallData.length - 4);
|
||||
// Decode call args for `ITransformERC20Feature.transformERC20()` as a struct.
|
||||
args = abi.decode(encodedStructArgs, (ExternalTransformERC20Args));
|
||||
}
|
||||
// Call `ITransformERC20Feature._transformERC20()` (internal variant).
|
||||
return
|
||||
_callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
ITransformERC20Feature._transformERC20.selector,
|
||||
ITransformERC20Feature.TransformERC20Args({
|
||||
taker: state.mtx.signer, // taker is mtx signer
|
||||
inputToken: args.inputToken,
|
||||
outputToken: args.outputToken,
|
||||
inputTokenAmount: args.inputTokenAmount,
|
||||
minOutputTokenAmount: args.minOutputTokenAmount,
|
||||
transformations: args.transformations,
|
||||
useSelfBalance: false,
|
||||
recipient: state.mtx.signer
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Extract arguments from call data by copying everything after the
|
||||
/// 4-byte selector into a new byte array.
|
||||
/// @param callData The call data from which arguments are to be extracted.
|
||||
/// @return args The extracted arguments as a byte array.
|
||||
function _extractArgumentsFromCallData(bytes memory callData) private pure returns (bytes memory args) {
|
||||
args = new bytes(callData.length - 4);
|
||||
uint256 fromMem;
|
||||
uint256 toMem;
|
||||
|
||||
assembly {
|
||||
fromMem := add(callData, 36) // skip length and 4-byte selector
|
||||
toMem := add(args, 32) // write after length prefix
|
||||
}
|
||||
|
||||
LibBytesV06.memCopy(toMem, fromMem, args.length);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/// @dev Execute a `INativeOrdersFeature.fillLimitOrder()` meta-transaction call
|
||||
/// by decoding the call args and translating the call to the internal
|
||||
/// `INativeOrdersFeature._fillLimitOrder()` variant, where we can override
|
||||
/// the taker address.
|
||||
function _executeFillLimitOrderCall(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||
LibNativeOrder.LimitOrder memory order;
|
||||
LibSignature.Signature memory signature;
|
||||
uint128 takerTokenFillAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(order, signature, takerTokenFillAmount) = abi.decode(
|
||||
args,
|
||||
(LibNativeOrder.LimitOrder, LibSignature.Signature, uint128)
|
||||
);
|
||||
|
||||
return
|
||||
_callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature._fillLimitOrder.selector,
|
||||
order,
|
||||
signature,
|
||||
takerTokenFillAmount,
|
||||
state.mtx.signer, // taker is mtx signer
|
||||
msg.sender
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a `INativeOrdersFeature.fillRfqOrder()` meta-transaction call
|
||||
/// by decoding the call args and translating the call to the internal
|
||||
/// `INativeOrdersFeature._fillRfqOrder()` variant, where we can override
|
||||
/// the taker address.
|
||||
function _executeFillRfqOrderCall(ExecuteState memory state) private returns (bytes memory returnResult) {
|
||||
LibNativeOrder.RfqOrder memory order;
|
||||
LibSignature.Signature memory signature;
|
||||
uint128 takerTokenFillAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(order, signature, takerTokenFillAmount) = abi.decode(
|
||||
args,
|
||||
(LibNativeOrder.RfqOrder, LibSignature.Signature, uint128)
|
||||
);
|
||||
|
||||
return
|
||||
_callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature._fillRfqOrder.selector,
|
||||
order,
|
||||
signature,
|
||||
takerTokenFillAmount,
|
||||
state.mtx.signer, // taker is mtx signer
|
||||
false,
|
||||
state.mtx.signer
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a `IMultiplexFeature.multiplexBatchSellTokenForToken()` meta-transaction
|
||||
/// call by decoding the call args and translating the call to the internal
|
||||
/// `IMultiplexFeature._multiplexBatchSell()` variant, where we can override the
|
||||
/// payer address.
|
||||
function _executeMultiplexBatchSellTokenForTokenCall(
|
||||
ExecuteState memory state
|
||||
) private returns (bytes memory returnResult) {
|
||||
IERC20Token inputToken;
|
||||
IERC20Token outputToken;
|
||||
IMultiplexFeature.BatchSellSubcall[] memory calls;
|
||||
uint256 sellAmount;
|
||||
uint256 minBuyAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(inputToken, outputToken, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||
args,
|
||||
(IERC20Token, IERC20Token, IMultiplexFeature.BatchSellSubcall[], uint256, uint256)
|
||||
);
|
||||
|
||||
return
|
||||
_callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
IMultiplexFeature._multiplexBatchSell.selector,
|
||||
IMultiplexFeature.BatchSellParams({
|
||||
inputToken: inputToken,
|
||||
outputToken: outputToken,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: state.mtx.signer,
|
||||
payer: state.mtx.signer
|
||||
}),
|
||||
minBuyAmount
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a `IMultiplexFeature.multiplexBatchSellTokenForEth()` meta-transaction
|
||||
/// call by decoding the call args and translating the call to the internal
|
||||
/// `IMultiplexFeature._multiplexBatchSellTokenForEth()` variant, where we can override the
|
||||
/// payer address.
|
||||
function _executeMultiplexBatchSellTokenForEthCall(
|
||||
ExecuteState memory state
|
||||
) private returns (bytes memory returnResult) {
|
||||
IERC20Token inputToken;
|
||||
IMultiplexFeature.BatchSellSubcall[] memory calls;
|
||||
uint256 sellAmount;
|
||||
uint256 minBuyAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(inputToken, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||
args,
|
||||
(IERC20Token, IMultiplexFeature.BatchSellSubcall[], uint256, uint256)
|
||||
);
|
||||
|
||||
returnResult = _callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
IMultiplexFeature._multiplexBatchSell.selector,
|
||||
IMultiplexFeature.BatchSellParams({
|
||||
inputToken: inputToken,
|
||||
outputToken: IERC20Token(WETH),
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: address(this),
|
||||
payer: state.mtx.signer
|
||||
}),
|
||||
minBuyAmount
|
||||
)
|
||||
);
|
||||
|
||||
// Unwrap and transfer WETH
|
||||
uint256 boughtAmount = abi.decode(returnResult, (uint256));
|
||||
WETH.withdraw(boughtAmount);
|
||||
_transferEth(state.mtx.signer, boughtAmount);
|
||||
}
|
||||
|
||||
/// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForToken()` meta-transaction
|
||||
/// call by decoding the call args and translating the call to the internal
|
||||
/// `IMultiplexFeature._multiplexMultiHopSell()` variant, where we can override the
|
||||
/// payer address.
|
||||
function _executeMultiplexMultiHopSellTokenForTokenCall(
|
||||
ExecuteState memory state
|
||||
) private returns (bytes memory returnResult) {
|
||||
address[] memory tokens;
|
||||
IMultiplexFeature.MultiHopSellSubcall[] memory calls;
|
||||
uint256 sellAmount;
|
||||
uint256 minBuyAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(tokens, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||
args,
|
||||
(address[], IMultiplexFeature.MultiHopSellSubcall[], uint256, uint256)
|
||||
);
|
||||
|
||||
return
|
||||
_callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
IMultiplexFeature._multiplexMultiHopSell.selector,
|
||||
IMultiplexFeature.MultiHopSellParams({
|
||||
tokens: tokens,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: state.mtx.signer,
|
||||
payer: state.mtx.signer
|
||||
}),
|
||||
minBuyAmount
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForEth()` meta-transaction
|
||||
/// call by decoding the call args and translating the call to the internal
|
||||
/// `IMultiplexFeature._multiplexMultiHopSellTokenForEth()` variant, where we can override the
|
||||
/// payer address.
|
||||
function _executeMultiplexMultiHopSellTokenForEthCall(
|
||||
ExecuteState memory state
|
||||
) private returns (bytes memory returnResult) {
|
||||
address[] memory tokens;
|
||||
IMultiplexFeature.MultiHopSellSubcall[] memory calls;
|
||||
uint256 sellAmount;
|
||||
uint256 minBuyAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(tokens, calls, sellAmount, minBuyAmount) = abi.decode(
|
||||
args,
|
||||
(address[], IMultiplexFeature.MultiHopSellSubcall[], uint256, uint256)
|
||||
);
|
||||
|
||||
require(
|
||||
tokens[tokens.length - 1] == address(WETH),
|
||||
"MetaTransactionsFeature::multiplexMultiHopSellTokenForEth/NOT_WETH"
|
||||
);
|
||||
|
||||
returnResult = _callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
IMultiplexFeature._multiplexMultiHopSell.selector,
|
||||
IMultiplexFeature.MultiHopSellParams({
|
||||
tokens: tokens,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: address(this),
|
||||
payer: state.mtx.signer
|
||||
}),
|
||||
minBuyAmount
|
||||
)
|
||||
);
|
||||
|
||||
// Unwrap and transfer WETH
|
||||
uint256 boughtAmount = abi.decode(returnResult, (uint256));
|
||||
WETH.withdraw(boughtAmount);
|
||||
_transferEth(state.mtx.signer, boughtAmount);
|
||||
}
|
||||
|
||||
/// @dev Make an arbitrary internal, meta-transaction call.
|
||||
/// Warning: Do not let unadulterated `callData` into this function.
|
||||
function _callSelf(bytes32 hash, bytes memory callData) private returns (bytes memory returnResult) {
|
||||
bool success;
|
||||
(success, returnResult) = address(this).call(callData);
|
||||
if (!success) {
|
||||
LibMetaTransactionsRichErrors.MetaTransactionCallFailedError(hash, callData, returnResult).rrevert();
|
||||
}
|
||||
}
|
||||
}
|
@ -70,7 +70,6 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
|
||||
_registerFeatureFunction(this.sellEthForTokenToUniswapV3.selector);
|
||||
_registerFeatureFunction(this.sellTokenForEthToUniswapV3.selector);
|
||||
_registerFeatureFunction(this.sellTokenForTokenToUniswapV3.selector);
|
||||
_registerFeatureFunction(this._sellTokenForTokenToUniswapV3.selector);
|
||||
_registerFeatureFunction(this._sellHeldTokenForTokenToUniswapV3.selector);
|
||||
_registerFeatureFunction(this.uniswapV3SwapCallback.selector);
|
||||
return LibMigrate.MIGRATE_SUCCESS;
|
||||
@ -140,23 +139,6 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
|
||||
buyAmount = _swap(encodedPath, sellAmount, minBuyAmount, msg.sender, _normalizeRecipient(recipient));
|
||||
}
|
||||
|
||||
/// @dev Sell a token for another token directly against uniswap v3. Internal variant.
|
||||
/// @param encodedPath Uniswap-encoded path.
|
||||
/// @param sellAmount amount of the first token in the path to sell.
|
||||
/// @param minBuyAmount Minimum amount of the last token in the path to buy.
|
||||
/// @param recipient The recipient of the bought tokens. Can be zero for payer.
|
||||
/// @param payer The address to pull the sold tokens from.
|
||||
/// @return buyAmount Amount of the last token in the path bought.
|
||||
function _sellTokenForTokenToUniswapV3(
|
||||
bytes memory encodedPath,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
address recipient,
|
||||
address payer
|
||||
) public override onlySelf returns (uint256 buyAmount) {
|
||||
buyAmount = _swap(encodedPath, sellAmount, minBuyAmount, payer, _normalizeRecipient(recipient, payer));
|
||||
}
|
||||
|
||||
/// @dev Sell a token for another token directly against uniswap v3.
|
||||
/// Private variant, uses tokens held by `address(this)`.
|
||||
/// @param encodedPath Uniswap-encoded path.
|
||||
@ -355,16 +337,8 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
|
||||
}
|
||||
}
|
||||
|
||||
// Convert null address values to alternative address.
|
||||
function _normalizeRecipient(
|
||||
address recipient,
|
||||
address alternative
|
||||
) private pure returns (address payable normalizedRecipient) {
|
||||
return recipient == address(0) ? payable(alternative) : payable(recipient);
|
||||
}
|
||||
|
||||
// Convert null address values to msg.sender.
|
||||
function _normalizeRecipient(address recipient) private view returns (address payable normalizedRecipient) {
|
||||
return _normalizeRecipient(recipient, msg.sender);
|
||||
return recipient == address(0) ? msg.sender : payable(recipient);
|
||||
}
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
import "../libs/LibSignature.sol";
|
||||
|
||||
/// @dev Meta-transactions feature.
|
||||
interface IMetaTransactionsFeatureV2 {
|
||||
/// @dev Describes an exchange proxy meta transaction.
|
||||
struct MetaTransactionFeeData {
|
||||
// ERC20 fee recipient
|
||||
address recipient;
|
||||
// ERC20 fee amount
|
||||
uint256 amount;
|
||||
}
|
||||
|
||||
struct MetaTransactionDataV2 {
|
||||
// Signer of meta-transaction. On whose behalf to execute the MTX.
|
||||
address payable signer;
|
||||
// Required sender, or NULL for anyone.
|
||||
address sender;
|
||||
// MTX is invalid after this time.
|
||||
uint256 expirationTimeSeconds;
|
||||
// Nonce to make this MTX unique.
|
||||
uint256 salt;
|
||||
// Encoded call data to a function on the exchange proxy.
|
||||
bytes callData;
|
||||
// ERC20 fee `signer` pays `sender`.
|
||||
IERC20Token feeToken;
|
||||
// ERC20 fees.
|
||||
MetaTransactionFeeData[] fees;
|
||||
}
|
||||
|
||||
/// @dev Emitted whenever a meta-transaction is executed via
|
||||
/// `executeMetaTransaction()` or `executeMetaTransactions()`.
|
||||
/// @param hash The EIP712 hash of the MetaTransactionDataV2 struct.
|
||||
/// @param selector The selector of the function being executed.
|
||||
/// @param signer Who to execute the meta-transaction on behalf of.
|
||||
/// @param sender Who executed the meta-transaction.
|
||||
event MetaTransactionExecuted(bytes32 hash, bytes4 indexed selector, address signer, address sender);
|
||||
|
||||
/// @dev Execute a single meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @param signature The signature by `mtx.signer`.
|
||||
/// @return returnResult The ABI-encoded result of the underlying call.
|
||||
function executeMetaTransactionV2(
|
||||
MetaTransactionDataV2 calldata mtx,
|
||||
LibSignature.Signature calldata signature
|
||||
) external returns (bytes memory returnResult);
|
||||
|
||||
/// @dev Execute multiple meta-transactions.
|
||||
/// @param mtxs The meta-transactions.
|
||||
/// @param signatures The signature by each respective `mtx.signer`.
|
||||
/// @return returnResults The ABI-encoded results of the underlying calls.
|
||||
function batchExecuteMetaTransactionsV2(
|
||||
MetaTransactionDataV2[] calldata mtxs,
|
||||
LibSignature.Signature[] calldata signatures
|
||||
) external returns (bytes[] memory returnResults);
|
||||
|
||||
/// @dev Get the block at which a meta-transaction has been executed.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionV2ExecutedBlock(
|
||||
MetaTransactionDataV2 calldata mtx
|
||||
) external view returns (uint256 blockNumber);
|
||||
|
||||
/// @dev Get the block at which a meta-transaction hash has been executed.
|
||||
/// @param mtxHash The EIP712 hash of the MetaTransactionDataV2 struct.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionV2HashExecutedBlock(bytes32 mtxHash) external view returns (uint256 blockNumber);
|
||||
|
||||
/// @dev Get the EIP712 hash of a meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return mtxHash The EIP712 hash of `mtx`.
|
||||
function getMetaTransactionV2Hash(MetaTransactionDataV2 calldata mtx) external view returns (bytes32 mtxHash);
|
||||
}
|
@ -46,8 +46,6 @@ interface IMultiplexFeature {
|
||||
bool useSelfBalance;
|
||||
// The recipient of the bought output tokens.
|
||||
address recipient;
|
||||
// The sender of the input tokens.
|
||||
address payer;
|
||||
}
|
||||
|
||||
// Represents a constituent call of a batch sell.
|
||||
@ -77,8 +75,6 @@ interface IMultiplexFeature {
|
||||
bool useSelfBalance;
|
||||
// The recipient of the bought output tokens.
|
||||
address recipient;
|
||||
// The sender of the input tokens.
|
||||
address payer;
|
||||
}
|
||||
|
||||
// Represents a constituent call of a multi-hop sell.
|
||||
@ -157,17 +153,6 @@ interface IMultiplexFeature {
|
||||
uint256 minBuyAmount
|
||||
) external returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Executes a multiplex BatchSell using the given
|
||||
/// parameters. Internal only.
|
||||
/// @param params The parameters for the BatchSell.
|
||||
/// @param minBuyAmount The minimum amount of `params.outputToken`
|
||||
/// that must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of `params.outputToken` bought.
|
||||
function _multiplexBatchSell(
|
||||
BatchSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) external returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Sells attached ETH via the given sequence of tokens
|
||||
/// and calls. `tokens[0]` must be WETH.
|
||||
/// The last token in `tokens` is the output token that
|
||||
@ -219,15 +204,4 @@ interface IMultiplexFeature {
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount
|
||||
) external returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Executes a multiplex MultiHopSell using the given
|
||||
/// parameters. Internal only.
|
||||
/// @param params The parameters for the MultiHopSell.
|
||||
/// @param minBuyAmount The minimum amount of the output token
|
||||
/// that must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of the output token bought.
|
||||
function _multiplexMultiHopSell(
|
||||
MultiHopSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) external returns (uint256 boughtAmount);
|
||||
}
|
||||
|
@ -54,21 +54,6 @@ interface IUniswapV3Feature {
|
||||
address recipient
|
||||
) external returns (uint256 buyAmount);
|
||||
|
||||
/// @dev Sell a token for another token directly against uniswap v3. Internal variant.
|
||||
/// @param encodedPath Uniswap-encoded path.
|
||||
/// @param sellAmount amount of the first token in the path to sell.
|
||||
/// @param minBuyAmount Minimum amount of the last token in the path to buy.
|
||||
/// @param recipient The recipient of the bought tokens. Can be zero for payer.
|
||||
/// @param payer The address to pull the sold tokens from.
|
||||
/// @return buyAmount Amount of the last token in the path bought.
|
||||
function _sellTokenForTokenToUniswapV3(
|
||||
bytes memory encodedPath,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
address recipient,
|
||||
address payer
|
||||
) external returns (uint256 buyAmount);
|
||||
|
||||
/// @dev Sell a token for another token directly against uniswap v3.
|
||||
/// Private variant, uses tokens held by `address(this)`.
|
||||
/// @param encodedPath Uniswap-encoded path.
|
||||
|
@ -80,11 +80,9 @@ contract MultiplexFeature is
|
||||
_registerFeatureFunction(this.multiplexBatchSellEthForToken.selector);
|
||||
_registerFeatureFunction(this.multiplexBatchSellTokenForEth.selector);
|
||||
_registerFeatureFunction(this.multiplexBatchSellTokenForToken.selector);
|
||||
_registerFeatureFunction(this._multiplexBatchSell.selector);
|
||||
_registerFeatureFunction(this.multiplexMultiHopSellEthForToken.selector);
|
||||
_registerFeatureFunction(this.multiplexMultiHopSellTokenForEth.selector);
|
||||
_registerFeatureFunction(this.multiplexMultiHopSellTokenForToken.selector);
|
||||
_registerFeatureFunction(this._multiplexMultiHopSell.selector);
|
||||
return LibMigrate.MIGRATE_SUCCESS;
|
||||
}
|
||||
|
||||
@ -105,15 +103,14 @@ contract MultiplexFeature is
|
||||
// WETH is now held by this contract,
|
||||
// so `useSelfBalance` is true.
|
||||
return
|
||||
_multiplexBatchSellPrivate(
|
||||
_multiplexBatchSell(
|
||||
BatchSellParams({
|
||||
inputToken: WETH,
|
||||
outputToken: outputToken,
|
||||
sellAmount: msg.value,
|
||||
calls: calls,
|
||||
useSelfBalance: true,
|
||||
recipient: msg.sender,
|
||||
payer: msg.sender
|
||||
recipient: msg.sender
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
@ -136,15 +133,14 @@ contract MultiplexFeature is
|
||||
// The outputToken is implicitly WETH. The `recipient`
|
||||
// of the WETH is set to this contract, since we
|
||||
// must unwrap the WETH and transfer the resulting ETH.
|
||||
boughtAmount = _multiplexBatchSellPrivate(
|
||||
boughtAmount = _multiplexBatchSell(
|
||||
BatchSellParams({
|
||||
inputToken: inputToken,
|
||||
outputToken: WETH,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: address(this),
|
||||
payer: msg.sender
|
||||
recipient: address(this)
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
@ -171,40 +167,26 @@ contract MultiplexFeature is
|
||||
uint256 minBuyAmount
|
||||
) public override returns (uint256 boughtAmount) {
|
||||
return
|
||||
_multiplexBatchSellPrivate(
|
||||
_multiplexBatchSell(
|
||||
BatchSellParams({
|
||||
inputToken: inputToken,
|
||||
outputToken: outputToken,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: msg.sender,
|
||||
payer: msg.sender
|
||||
recipient: msg.sender
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Executes a batch sell and checks that at least
|
||||
/// `minBuyAmount` of `outputToken` was bought. Internal variant.
|
||||
/// @param params Batch sell parameters.
|
||||
/// @param minBuyAmount The minimum amount of `outputToken` that
|
||||
/// must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function _multiplexBatchSell(
|
||||
BatchSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) public override onlySelf returns (uint256 boughtAmount) {
|
||||
return _multiplexBatchSellPrivate(params, minBuyAmount);
|
||||
}
|
||||
|
||||
/// @dev Executes a batch sell and checks that at least
|
||||
/// `minBuyAmount` of `outputToken` was bought.
|
||||
/// @param params Batch sell parameters.
|
||||
/// @param minBuyAmount The minimum amount of `outputToken` that
|
||||
/// must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function _multiplexBatchSellPrivate(
|
||||
function _multiplexBatchSell(
|
||||
BatchSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) private returns (uint256 boughtAmount) {
|
||||
@ -244,14 +226,13 @@ contract MultiplexFeature is
|
||||
// WETH is now held by this contract,
|
||||
// so `useSelfBalance` is true.
|
||||
return
|
||||
_multiplexMultiHopSellPrivate(
|
||||
_multiplexMultiHopSell(
|
||||
MultiHopSellParams({
|
||||
tokens: tokens,
|
||||
sellAmount: msg.value,
|
||||
calls: calls,
|
||||
useSelfBalance: true,
|
||||
recipient: msg.sender,
|
||||
payer: msg.sender
|
||||
recipient: msg.sender
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
@ -281,14 +262,13 @@ contract MultiplexFeature is
|
||||
);
|
||||
// The `recipient of the WETH is set to this contract, since
|
||||
// we must unwrap the WETH and transfer the resulting ETH.
|
||||
boughtAmount = _multiplexMultiHopSellPrivate(
|
||||
boughtAmount = _multiplexMultiHopSell(
|
||||
MultiHopSellParams({
|
||||
tokens: tokens,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: address(this),
|
||||
payer: msg.sender
|
||||
recipient: address(this)
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
@ -317,38 +297,25 @@ contract MultiplexFeature is
|
||||
uint256 minBuyAmount
|
||||
) public override returns (uint256 boughtAmount) {
|
||||
return
|
||||
_multiplexMultiHopSellPrivate(
|
||||
_multiplexMultiHopSell(
|
||||
MultiHopSellParams({
|
||||
tokens: tokens,
|
||||
sellAmount: sellAmount,
|
||||
calls: calls,
|
||||
useSelfBalance: false,
|
||||
recipient: msg.sender,
|
||||
payer: msg.sender
|
||||
recipient: msg.sender
|
||||
}),
|
||||
minBuyAmount
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Executes a multi-hop sell. Internal variant.
|
||||
/// @param params Multi-hop sell parameters.
|
||||
/// @param minBuyAmount The minimum amount of output tokens that
|
||||
/// must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of output tokens bought.
|
||||
function _multiplexMultiHopSell(
|
||||
MultiHopSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) public override onlySelf returns (uint256 boughtAmount) {
|
||||
return _multiplexMultiHopSellPrivate(params, minBuyAmount);
|
||||
}
|
||||
|
||||
/// @dev Executes a multi-hop sell and checks that at least
|
||||
/// `minBuyAmount` of output tokens were bought.
|
||||
/// @param params Multi-hop sell parameters.
|
||||
/// @param minBuyAmount The minimum amount of output tokens that
|
||||
/// must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of output tokens bought.
|
||||
function _multiplexMultiHopSellPrivate(
|
||||
function _multiplexMultiHopSell(
|
||||
MultiHopSellParams memory params,
|
||||
uint256 minBuyAmount
|
||||
) private returns (uint256 boughtAmount) {
|
||||
@ -420,14 +387,14 @@ contract MultiplexFeature is
|
||||
// amount of the multi-hop fill.
|
||||
state.outputTokenAmount = params.sellAmount;
|
||||
// The first call may expect the input tokens to be held by
|
||||
// `payer`, `address(this)`, or some other address.
|
||||
// `msg.sender`, `address(this)`, or some other address.
|
||||
// Compute the expected address and transfer the input tokens
|
||||
// there if necessary.
|
||||
state.from = _computeHopTarget(params, 0);
|
||||
// If the input tokens are currently held by `payer` but
|
||||
// If the input tokens are currently held by `msg.sender` but
|
||||
// the first hop expects them elsewhere, perform a `transferFrom`.
|
||||
if (!params.useSelfBalance && state.from != params.payer) {
|
||||
_transferERC20TokensFrom(IERC20Token(params.tokens[0]), params.payer, state.from, params.sellAmount);
|
||||
if (!params.useSelfBalance && state.from != msg.sender) {
|
||||
_transferERC20TokensFrom(IERC20Token(params.tokens[0]), msg.sender, state.from, params.sellAmount);
|
||||
}
|
||||
// If the input tokens are currently held by `address(this)` but
|
||||
// the first hop expects them elsewhere, perform a `transfer`.
|
||||
@ -444,13 +411,11 @@ contract MultiplexFeature is
|
||||
if (subcall.id == MultiplexSubcall.UniswapV2) {
|
||||
_multiHopSellUniswapV2(state, params, subcall.data);
|
||||
} else if (subcall.id == MultiplexSubcall.UniswapV3) {
|
||||
_multiHopSellUniswapV3(state, params, subcall.data);
|
||||
_multiHopSellUniswapV3(state, subcall.data);
|
||||
} else if (subcall.id == MultiplexSubcall.LiquidityProvider) {
|
||||
_multiHopSellLiquidityProvider(state, params, subcall.data);
|
||||
} else if (subcall.id == MultiplexSubcall.BatchSell) {
|
||||
_nestedBatchSell(state, params, subcall.data);
|
||||
} else if (subcall.id == MultiplexSubcall.OTC) {
|
||||
_multiHopSellOtcOrder(state, params, subcall.data);
|
||||
} else {
|
||||
revert("MultiplexFeature::_executeMultiHopSell/INVALID_SUBCALL");
|
||||
}
|
||||
@ -478,8 +443,6 @@ contract MultiplexFeature is
|
||||
// Likewise, the recipient of the multi-hop sell is
|
||||
// equal to the recipient of its containing batch sell.
|
||||
multiHopParams.recipient = params.recipient;
|
||||
// The payer is the same too.
|
||||
multiHopParams.payer = params.payer;
|
||||
// Execute the nested multi-hop sell.
|
||||
uint256 outputTokenAmount = _executeMultiHopSell(multiHopParams).outputTokenAmount;
|
||||
// Increment the sold and bought amounts.
|
||||
@ -506,7 +469,7 @@ contract MultiplexFeature is
|
||||
// If the nested batch sell is the first hop
|
||||
// and `useSelfBalance` for the containing multi-
|
||||
// hop sell is false, the nested batch sell should
|
||||
// pull tokens from `payer` (so `batchSellParams.useSelfBalance`
|
||||
// pull tokens from `msg.sender` (so `batchSellParams.useSelfBalance`
|
||||
// should be false). Otherwise `batchSellParams.useSelfBalance`
|
||||
// should be true.
|
||||
batchSellParams.useSelfBalance = state.hopIndex > 0 || params.useSelfBalance;
|
||||
@ -514,8 +477,6 @@ contract MultiplexFeature is
|
||||
// that should receive the output tokens of the
|
||||
// batch sell.
|
||||
batchSellParams.recipient = state.to;
|
||||
// payer shound be the same too.
|
||||
batchSellParams.payer = params.payer;
|
||||
// Execute the nested batch sell.
|
||||
state.outputTokenAmount = _executeBatchSell(batchSellParams).boughtAmount;
|
||||
}
|
||||
@ -544,33 +505,29 @@ contract MultiplexFeature is
|
||||
// is executed, so we the target is the address encoded
|
||||
// in the subcall data.
|
||||
(target, ) = abi.decode(subcall.data, (address, bytes));
|
||||
} else if (
|
||||
subcall.id == MultiplexSubcall.UniswapV3 ||
|
||||
subcall.id == MultiplexSubcall.BatchSell ||
|
||||
subcall.id == MultiplexSubcall.OTC
|
||||
) {
|
||||
} else if (subcall.id == MultiplexSubcall.UniswapV3 || subcall.id == MultiplexSubcall.BatchSell) {
|
||||
// UniswapV3 uses a callback to pull in the tokens being
|
||||
// sold to it. The callback implemented in `UniswapV3Feature`
|
||||
// can either:
|
||||
// - call `transferFrom` to move tokens from `payer` to the
|
||||
// - call `transferFrom` to move tokens from `msg.sender` to the
|
||||
// UniswapV3 pool, or
|
||||
// - call `transfer` to move tokens from `address(this)` to the
|
||||
// UniswapV3 pool.
|
||||
// A nested batch sell is similar, in that it can either:
|
||||
// - use tokens from `payer`, or
|
||||
// - use tokens from `msg.sender`, or
|
||||
// - use tokens held by `address(this)`.
|
||||
|
||||
// Suppose UniswapV3/BatchSell is the first call in the multi-hop
|
||||
// path. The input tokens are either held by `payer`,
|
||||
// path. The input tokens are either held by `msg.sender`,
|
||||
// or in the case of `multiplexMultiHopSellEthForToken` WETH is
|
||||
// held by `address(this)`. The target is set accordingly.
|
||||
|
||||
// If this is _not_ the first call in the multi-hop path, we
|
||||
// are dealing with an "intermediate" token in the multi-hop path,
|
||||
// which `payer` may not have an allowance set for. Thus
|
||||
// which `msg.sender` may not have an allowance set for. Thus
|
||||
// target must be set to `address(this)` for `i > 0`.
|
||||
if (i == 0 && !params.useSelfBalance) {
|
||||
target = params.payer;
|
||||
target = msg.sender;
|
||||
} else {
|
||||
target = address(this);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ abstract contract MultiplexLiquidityProvider is FixinCommon, FixinTokenSpender {
|
||||
_transferERC20Tokens(params.inputToken, provider, sellAmount);
|
||||
} else {
|
||||
// Otherwise, transfer the input tokens from `msg.sender`.
|
||||
_transferERC20TokensFrom(params.inputToken, params.payer, provider, sellAmount);
|
||||
_transferERC20TokensFrom(params.inputToken, msg.sender, provider, sellAmount);
|
||||
}
|
||||
// Cache the recipient's balance of the output token.
|
||||
uint256 balanceBefore = params.outputToken.balanceOf(params.recipient);
|
||||
|
@ -55,7 +55,7 @@ abstract contract MultiplexOtc is FixinEIP712 {
|
||||
order,
|
||||
signature,
|
||||
sellAmount.safeDowncastToUint128(),
|
||||
params.payer,
|
||||
msg.sender,
|
||||
params.useSelfBalance,
|
||||
params.recipient
|
||||
)
|
||||
@ -65,34 +65,4 @@ abstract contract MultiplexOtc is FixinEIP712 {
|
||||
state.boughtAmount = state.boughtAmount.safeAdd(makerTokenFilledAmount);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function _multiHopSellOtcOrder(
|
||||
IMultiplexFeature.MultiHopSellState memory state,
|
||||
IMultiplexFeature.MultiHopSellParams memory params,
|
||||
bytes memory wrappedCallData
|
||||
) internal {
|
||||
// Decode the Otc order, and signature.
|
||||
(LibNativeOrder.OtcOrder memory order, LibSignature.Signature memory signature) = abi.decode(
|
||||
wrappedCallData,
|
||||
(LibNativeOrder.OtcOrder, LibSignature.Signature)
|
||||
);
|
||||
//Make sure that the otc orders maker and taker tokens match the fill sequence in params.tokens[]
|
||||
require(
|
||||
address(order.takerToken) == params.tokens[state.hopIndex] &&
|
||||
address(order.makerToken) == params.tokens[state.hopIndex + 1],
|
||||
"MultiplexOtcOrder::_multiHopSellOtcOrder/INVALID_TOKENS"
|
||||
);
|
||||
// Try filling the Otc order. Bubble up reverts.
|
||||
(uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount) = IOtcOrdersFeature(address(this))
|
||||
._fillOtcOrder(
|
||||
order,
|
||||
signature,
|
||||
state.outputTokenAmount.safeDowncastToUint128(),
|
||||
state.from,
|
||||
params.useSelfBalance,
|
||||
state.to
|
||||
);
|
||||
//store the bought amount for the next hop
|
||||
state.outputTokenAmount = makerTokenFilledAmount;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ abstract contract MultiplexRfq is FixinEIP712 {
|
||||
order,
|
||||
signature,
|
||||
sellAmount.safeDowncastToUint128(),
|
||||
params.payer,
|
||||
msg.sender,
|
||||
params.useSelfBalance,
|
||||
params.recipient
|
||||
)
|
||||
|
@ -30,8 +30,8 @@ abstract contract MultiplexTransformERC20 {
|
||||
) internal {
|
||||
ITransformERC20Feature.TransformERC20Args memory args;
|
||||
// We want the TransformedERC20 event to have
|
||||
// `payer` as the taker.
|
||||
args.taker = payable(params.payer);
|
||||
// `msg.sender` as the taker.
|
||||
args.taker = msg.sender;
|
||||
args.inputToken = params.inputToken;
|
||||
args.outputToken = params.outputToken;
|
||||
args.inputTokenAmount = sellAmount;
|
||||
|
@ -77,7 +77,7 @@ abstract contract MultiplexUniswapV2 is FixinCommon, FixinTokenSpender {
|
||||
if (params.useSelfBalance) {
|
||||
_transferERC20Tokens(IERC20Token(tokens[0]), firstPairAddress, sellAmount);
|
||||
} else {
|
||||
_transferERC20TokensFrom(IERC20Token(tokens[0]), params.payer, firstPairAddress, sellAmount);
|
||||
_transferERC20TokensFrom(IERC20Token(tokens[0]), msg.sender, firstPairAddress, sellAmount);
|
||||
}
|
||||
// Execute the Uniswap/Sushiswap trade.
|
||||
return _sellToUniswapV2(tokens, sellAmount, isSushi, firstPairAddress, params.recipient);
|
||||
|
@ -45,16 +45,16 @@ abstract contract MultiplexUniswapV3 is FixinTokenSpender {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Otherwise, we self-call `_sellTokenForTokenToUniswapV3`,
|
||||
// which pulls the input token from a specified `payer`.
|
||||
(success, resultData) = address(this).call(
|
||||
// Otherwise, we self-delegatecall the normal variant
|
||||
// `sellTokenForTokenToUniswapV3`, which pulls the input token
|
||||
// from `msg.sender`.
|
||||
(success, resultData) = address(this).delegatecall(
|
||||
abi.encodeWithSelector(
|
||||
IUniswapV3Feature._sellTokenForTokenToUniswapV3.selector,
|
||||
IUniswapV3Feature.sellTokenForTokenToUniswapV3.selector,
|
||||
wrappedCallData,
|
||||
sellAmount,
|
||||
0,
|
||||
params.recipient,
|
||||
params.payer
|
||||
params.recipient
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -69,7 +69,6 @@ abstract contract MultiplexUniswapV3 is FixinTokenSpender {
|
||||
|
||||
function _multiHopSellUniswapV3(
|
||||
IMultiplexFeature.MultiHopSellState memory state,
|
||||
IMultiplexFeature.MultiHopSellParams memory params,
|
||||
bytes memory wrappedCallData
|
||||
) internal {
|
||||
bool success;
|
||||
@ -88,16 +87,16 @@ abstract contract MultiplexUniswapV3 is FixinTokenSpender {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Otherwise, we self-call `_sellTokenForTokenToUniswapV3`,
|
||||
// which pulls the input token from `payer`.
|
||||
(success, resultData) = address(this).call(
|
||||
// Otherwise, we self-delegatecall the normal variant
|
||||
// `sellTokenForTokenToUniswapV3`, which pulls the input token
|
||||
// from `msg.sender`.
|
||||
(success, resultData) = address(this).delegatecall(
|
||||
abi.encodeWithSelector(
|
||||
IUniswapV3Feature._sellTokenForTokenToUniswapV3.selector,
|
||||
IUniswapV3Feature.sellTokenForTokenToUniswapV3.selector,
|
||||
wrappedCallData,
|
||||
state.outputTokenAmount,
|
||||
0,
|
||||
state.to,
|
||||
params.payer
|
||||
state.to
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./LibStorage.sol";
|
||||
|
||||
/// @dev Storage helpers for the `MetaTransactions` feature.
|
||||
library LibMetaTransactionsV2Storage {
|
||||
/// @dev Storage bucket for this feature.
|
||||
struct Storage {
|
||||
// The block number when a hash was executed.
|
||||
mapping(bytes32 => uint256) mtxHashToExecutedBlockNumber;
|
||||
}
|
||||
|
||||
/// @dev Get the storage bucket for this contract.
|
||||
function getStorage() internal pure returns (Storage storage stor) {
|
||||
uint256 storageSlot = LibStorage.getStorageSlot(LibStorage.StorageId.MetaTransactionsV2);
|
||||
// Dip into assembly to change the slot pointed to by the local variable `stor`.
|
||||
// solhint-disable-next-line max-line-length
|
||||
// See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
|
||||
assembly {
|
||||
stor_slot := storageSlot
|
||||
}
|
||||
}
|
||||
}
|
@ -34,8 +34,7 @@ library LibStorage {
|
||||
NativeOrders,
|
||||
OtcOrders,
|
||||
ERC721Orders,
|
||||
ERC1155Orders,
|
||||
MetaTransactionsV2
|
||||
ERC1155Orders
|
||||
}
|
||||
|
||||
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced slots to storage bucket variables
|
||||
|
@ -23,14 +23,12 @@ abstract contract AbstractBridgeAdapter is IBridgeAdapter {
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
// Skip chain id validation on Ganache (1337), Anvil (31337), Goerli (5), Mumbai (80001), Base Goerli (84531),
|
||||
// Sepolia (11155111)
|
||||
// Skip chain id validation on Ganache (1337), Anvil (31337), Goerli (5), Mumbai (80001), Base Goerli (84531)
|
||||
bool skipValidation = (chainId == 1337 ||
|
||||
chainId == 31337 ||
|
||||
chainId == 5 ||
|
||||
chainId == 80001 ||
|
||||
chainId == 84531 ||
|
||||
chainId == 11155111);
|
||||
chainId == 84531);
|
||||
|
||||
if (chainId != expectedChainId && !skipValidation) {
|
||||
revert(string(abi.encodePacked(expectedChainName, "BridgeAdapter.constructor: wrong chain ID")));
|
||||
|
@ -26,7 +26,6 @@ import "./mixins/MixinKyberDmm.sol";
|
||||
import "./mixins/MixinKyberElastic.sol";
|
||||
import "./mixins/MixinGMX.sol";
|
||||
import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinTraderJoeV2.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
import "./mixins/MixinWOOFi.sol";
|
||||
@ -43,7 +42,6 @@ contract ArbitrumBridgeAdapter is
|
||||
MixinKyberElastic,
|
||||
MixinGMX,
|
||||
MixinNerve,
|
||||
MixinTraderJoeV2,
|
||||
MixinUniswapV3,
|
||||
MixinUniswapV2,
|
||||
MixinWOOFi,
|
||||
@ -99,11 +97,6 @@ contract ArbitrumBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.TRADERJOEV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeTraderJoeV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.GMX) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
|
@ -26,9 +26,7 @@ import "./mixins/MixinKyberElastic.sol";
|
||||
import "./mixins/MixinAaveV2.sol";
|
||||
import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinPlatypus.sol";
|
||||
import "./mixins/MixinTraderJoeV2.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinWOOFi.sol";
|
||||
import "./mixins/MixinZeroExBridge.sol";
|
||||
|
||||
@ -43,9 +41,7 @@ contract AvalancheBridgeAdapter is
|
||||
MixinAaveV2,
|
||||
MixinNerve,
|
||||
MixinPlatypus,
|
||||
MixinTraderJoeV2,
|
||||
MixinUniswapV2,
|
||||
MixinUniswapV3,
|
||||
MixinWOOFi,
|
||||
MixinZeroExBridge
|
||||
{
|
||||
@ -74,11 +70,6 @@ contract AvalancheBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV3(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.NERVE) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
@ -109,11 +100,6 @@ contract AvalancheBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradePlatypus(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.TRADERJOEV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeTraderJoeV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.WOOFI) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
|
@ -22,11 +22,9 @@ import "./mixins/MixinDodo.sol";
|
||||
import "./mixins/MixinDodoV2.sol";
|
||||
import "./mixins/MixinKyberDmm.sol";
|
||||
import "./mixins/MixinKyberElastic.sol";
|
||||
import "./mixins/MixinMaverickV1.sol";
|
||||
import "./mixins/MixinMooniswap.sol";
|
||||
import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinWOOFi.sol";
|
||||
import "./mixins/MixinZeroExBridge.sol";
|
||||
|
||||
@ -37,11 +35,9 @@ contract BSCBridgeAdapter is
|
||||
MixinDodoV2,
|
||||
MixinKyberDmm,
|
||||
MixinKyberElastic,
|
||||
MixinMaverickV1,
|
||||
MixinMooniswap,
|
||||
MixinNerve,
|
||||
MixinUniswapV2,
|
||||
MixinUniswapV3,
|
||||
MixinWOOFi,
|
||||
MixinZeroExBridge
|
||||
{
|
||||
@ -65,11 +61,6 @@ contract BSCBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV3(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MOONISWAP) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
@ -105,11 +96,6 @@ contract BSCBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeWOOFi(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MAVERICKV1) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMaverickV1(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNKNOWN) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
|
@ -1,93 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./AbstractBridgeAdapter.sol";
|
||||
import "./BridgeProtocols.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
import "./mixins/MixinBalancerV2Batch.sol";
|
||||
import "./mixins/MixinCurve.sol";
|
||||
import "./mixins/MixinCurveV2.sol";
|
||||
import "./mixins/MixinMaverickV1.sol";
|
||||
import "./mixins/MixinSolidly.sol";
|
||||
import "./mixins/MixinVelodromeV2.sol";
|
||||
|
||||
contract BaseBridgeAdapter is
|
||||
AbstractBridgeAdapter(8453, "Base"),
|
||||
MixinUniswapV3,
|
||||
MixinUniswapV2,
|
||||
MixinBalancerV2Batch,
|
||||
MixinCurve,
|
||||
MixinCurveV2,
|
||||
MixinMaverickV1,
|
||||
MixinSolidly,
|
||||
MixinVelodromeV2
|
||||
{
|
||||
constructor(IEtherToken weth) public MixinCurve(weth) {}
|
||||
|
||||
function _trade(
|
||||
BridgeOrder memory order,
|
||||
IERC20Token sellToken,
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bool dryRun
|
||||
) internal override returns (uint256 boughtAmount, bool supportedSource) {
|
||||
uint128 protocolId = uint128(uint256(order.source) >> 128);
|
||||
if (protocolId == BridgeProtocols.CURVE) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeCurve(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.CURVEV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeCurveV2(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNISWAPV3) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV3(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV2(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.SOLIDLY) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeSolidly(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.BALANCERV2BATCH) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeBalancerV2Batch(sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MAVERICKV1) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMaverickV1(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.VELODROMEV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeVelodromeV2(sellToken, sellAmount, order.bridgeData);
|
||||
}
|
||||
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./AbstractBridgeAdapter.sol";
|
||||
import "./BridgeProtocols.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
|
||||
contract BaseGoerliBridgeAdapter is AbstractBridgeAdapter(84531, "Base Goerli"), MixinUniswapV3, MixinUniswapV2 {
|
||||
function _trade(
|
||||
BridgeOrder memory order,
|
||||
IERC20Token sellToken,
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bool dryRun
|
||||
) internal override returns (uint256 boughtAmount, bool supportedSource) {
|
||||
uint128 protocolId = uint128(uint256(order.source) >> 128);
|
||||
if (protocolId == BridgeProtocols.UNISWAPV3) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV3(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeUniswapV2(buyToken, sellAmount, order.bridgeData);
|
||||
}
|
||||
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);
|
||||
}
|
||||
}
|
@ -55,8 +55,4 @@ library BridgeProtocols {
|
||||
uint128 internal constant WOOFI = 31;
|
||||
uint128 internal constant AAVEV3 = 32;
|
||||
uint128 internal constant KYBERELASTIC = 33;
|
||||
uint128 internal constant BARTER = 34;
|
||||
uint128 internal constant TRADERJOEV2 = 35;
|
||||
uint128 internal constant VELODROMEV2 = 36;
|
||||
uint128 internal constant MAVERICKV1 = 37;
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import "./BridgeProtocols.sol";
|
||||
import "./mixins/MixinAaveV2.sol";
|
||||
import "./mixins/MixinBalancer.sol";
|
||||
import "./mixins/MixinBalancerV2Batch.sol";
|
||||
import "./mixins/MixinBancor.sol";
|
||||
import "./mixins/MixinBancorV3.sol";
|
||||
import "./mixins/MixinBarter.sol";
|
||||
import "./mixins/MixinCompound.sol";
|
||||
import "./mixins/MixinCurve.sol";
|
||||
import "./mixins/MixinCurveV2.sol";
|
||||
@ -32,8 +32,9 @@ import "./mixins/MixinKyberDmm.sol";
|
||||
import "./mixins/MixinKyberElastic.sol";
|
||||
import "./mixins/MixinLido.sol";
|
||||
import "./mixins/MixinMakerPSM.sol";
|
||||
import "./mixins/MixinMaverickV1.sol";
|
||||
import "./mixins/MixinMStable.sol";
|
||||
import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinShell.sol";
|
||||
import "./mixins/MixinSynthetix.sol";
|
||||
import "./mixins/MixinUniswap.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
@ -45,8 +46,8 @@ contract EthereumBridgeAdapter is
|
||||
MixinAaveV2,
|
||||
MixinBalancer,
|
||||
MixinBalancerV2Batch,
|
||||
MixinBancor,
|
||||
MixinBancorV3,
|
||||
MixinBarter,
|
||||
MixinCompound,
|
||||
MixinCurve,
|
||||
MixinCurveV2,
|
||||
@ -57,8 +58,9 @@ contract EthereumBridgeAdapter is
|
||||
MixinKyberElastic,
|
||||
MixinLido,
|
||||
MixinMakerPSM,
|
||||
MixinMaverickV1,
|
||||
MixinMStable,
|
||||
MixinNerve,
|
||||
MixinShell,
|
||||
MixinSynthetix,
|
||||
MixinUniswap,
|
||||
MixinUniswapV2,
|
||||
@ -67,7 +69,15 @@ contract EthereumBridgeAdapter is
|
||||
{
|
||||
constructor(
|
||||
IEtherToken weth
|
||||
) public MixinBancorV3(weth) MixinCompound(weth) MixinCurve(weth) MixinLido(weth) MixinUniswap(weth) {}
|
||||
)
|
||||
public
|
||||
MixinBancor(weth)
|
||||
MixinBancorV3(weth)
|
||||
MixinCompound(weth)
|
||||
MixinCurve(weth)
|
||||
MixinLido(weth)
|
||||
MixinUniswap(weth)
|
||||
{}
|
||||
|
||||
function _trade(
|
||||
BridgeOrder memory order,
|
||||
@ -117,6 +127,16 @@ contract EthereumBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMakerPsm(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MSTABLE) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMStable(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.SHELL) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeShell(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.DODO) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
@ -132,6 +152,11 @@ contract EthereumBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeCryptoCom(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.BANCOR) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeBancor(buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.NERVE) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
@ -172,16 +197,6 @@ contract EthereumBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeSynthetix(sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.BARTER) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeBarter(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MAVERICKV1) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMaverickV1(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.UNKNOWN) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
|
@ -26,7 +26,6 @@ import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinSolidly.sol";
|
||||
import "./mixins/MixinSynthetix.sol";
|
||||
import "./mixins/MixinUniswapV3.sol";
|
||||
import "./mixins/MixinVelodromeV2.sol";
|
||||
import "./mixins/MixinWOOFi.sol";
|
||||
import "./mixins/MixinZeroExBridge.sol";
|
||||
|
||||
@ -40,7 +39,6 @@ contract OptimismBridgeAdapter is
|
||||
MixinNerve,
|
||||
MixinSynthetix,
|
||||
MixinUniswapV3,
|
||||
MixinVelodromeV2,
|
||||
MixinSolidly,
|
||||
MixinWOOFi,
|
||||
MixinZeroExBridge
|
||||
@ -111,11 +109,6 @@ contract OptimismBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeKyberElastic(sellToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.VELODROMEV2) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeVelodromeV2(sellToken, sellAmount, order.bridgeData);
|
||||
}
|
||||
|
||||
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);
|
||||
|
@ -26,6 +26,7 @@ import "./mixins/MixinDodo.sol";
|
||||
import "./mixins/MixinDodoV2.sol";
|
||||
import "./mixins/MixinKyberDmm.sol";
|
||||
import "./mixins/MixinKyberElastic.sol";
|
||||
import "./mixins/MixinMStable.sol";
|
||||
import "./mixins/MixinNerve.sol";
|
||||
import "./mixins/MixinSolidly.sol";
|
||||
import "./mixins/MixinUniswapV2.sol";
|
||||
@ -44,6 +45,7 @@ contract PolygonBridgeAdapter is
|
||||
MixinDodoV2,
|
||||
MixinKyberDmm,
|
||||
MixinKyberElastic,
|
||||
MixinMStable,
|
||||
MixinNerve,
|
||||
MixinUniswapV2,
|
||||
MixinUniswapV3,
|
||||
@ -86,6 +88,11 @@ contract PolygonBridgeAdapter is
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeBalancerV2Batch(sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.MSTABLE) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
}
|
||||
boughtAmount = _tradeMStable(sellToken, buyToken, sellAmount, order.bridgeData);
|
||||
} else if (protocolId == BridgeProtocols.DODO) {
|
||||
if (dryRun) {
|
||||
return (0, true);
|
||||
|
@ -0,0 +1,93 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
|
||||
import "../IBridgeAdapter.sol";
|
||||
|
||||
interface IBancorNetwork {
|
||||
function convertByPath(
|
||||
IERC20Token[] calldata _path,
|
||||
uint256 _amount,
|
||||
uint256 _minReturn,
|
||||
address _beneficiary,
|
||||
address _affiliateAccount,
|
||||
uint256 _affiliateFee
|
||||
) external payable returns (uint256);
|
||||
}
|
||||
|
||||
contract MixinBancor {
|
||||
/// @dev Bancor ETH pseudo-address.
|
||||
IERC20Token public constant BANCOR_ETH_ADDRESS = IERC20Token(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
|
||||
IEtherToken private immutable WETH;
|
||||
|
||||
constructor(IEtherToken weth) public {
|
||||
WETH = weth;
|
||||
}
|
||||
|
||||
function _tradeBancor(
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
// Decode the bridge data.
|
||||
IBancorNetwork bancorNetworkAddress;
|
||||
IERC20Token[] memory path;
|
||||
{
|
||||
address[] memory _path;
|
||||
(bancorNetworkAddress, _path) = abi.decode(bridgeData, (IBancorNetwork, address[]));
|
||||
// To get around `abi.decode()` not supporting interface array types.
|
||||
assembly {
|
||||
path := _path
|
||||
}
|
||||
}
|
||||
|
||||
require(path.length >= 2, "MixinBancor/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(
|
||||
path[path.length - 1] == buyToken || (path[path.length - 1] == BANCOR_ETH_ADDRESS && buyToken == WETH),
|
||||
"MixinBancor/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
|
||||
);
|
||||
|
||||
uint256 payableAmount = 0;
|
||||
// If it's ETH in the path then withdraw from WETH
|
||||
// The Bancor path will have ETH as the 0xeee address
|
||||
// Bancor expects to be paid in ETH not WETH
|
||||
if (path[0] == BANCOR_ETH_ADDRESS) {
|
||||
WETH.withdraw(sellAmount);
|
||||
payableAmount = sellAmount;
|
||||
} else {
|
||||
// Grant an allowance to the Bancor Network.
|
||||
LibERC20TokenV06.approveIfBelow(path[0], address(bancorNetworkAddress), sellAmount);
|
||||
}
|
||||
|
||||
// Convert the tokens
|
||||
boughtAmount = bancorNetworkAddress.convertByPath{value: payableAmount}(
|
||||
path, // path originating with source token and terminating in destination token
|
||||
sellAmount, // amount of source token to trade
|
||||
1, // minimum amount of destination token expected to receive
|
||||
address(this), // beneficiary
|
||||
address(0), // affiliateAccount; no fee paid
|
||||
0 // affiliateFee; no fee paid
|
||||
);
|
||||
if (path[path.length - 1] == BANCOR_ETH_ADDRESS) {
|
||||
WETH.deposit{value: boughtAmount}();
|
||||
}
|
||||
|
||||
return boughtAmount;
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
|
||||
interface IMaverickV1Router {
|
||||
struct ExactInputSingleParams {
|
||||
address tokenIn;
|
||||
address tokenOut;
|
||||
address pool;
|
||||
address recipient;
|
||||
uint256 deadline;
|
||||
uint256 amountIn;
|
||||
uint256 amountOutMinimum;
|
||||
uint256 sqrtPriceLimitD18;
|
||||
}
|
||||
|
||||
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
|
||||
}
|
||||
|
||||
contract MixinMaverickV1 {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
|
||||
function _tradeMaverickV1(
|
||||
IERC20Token sellToken,
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
(IMaverickV1Router router, address pool) = abi.decode(bridgeData, (IMaverickV1Router, address));
|
||||
|
||||
// Grant the MaverickV1 router an allowance to sell the sellToken
|
||||
sellToken.approveIfBelow(address(router), sellAmount);
|
||||
|
||||
boughtAmount = router.exactInputSingle(
|
||||
IMaverickV1Router.ExactInputSingleParams({
|
||||
tokenIn: address(sellToken),
|
||||
tokenOut: address(buyToken),
|
||||
pool: pool,
|
||||
recipient: address(this),
|
||||
deadline: block.timestamp,
|
||||
amountIn: sellAmount,
|
||||
amountOutMinimum: 1,
|
||||
sqrtPriceLimitD18: 0
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -17,25 +17,41 @@ pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||
|
||||
contract MixinBarter {
|
||||
interface IShell {
|
||||
function originSwap(
|
||||
IERC20Token from,
|
||||
IERC20Token to,
|
||||
uint256 fromAmount,
|
||||
uint256 minTargetAmount,
|
||||
uint256 deadline
|
||||
) external returns (uint256 toAmount);
|
||||
}
|
||||
|
||||
contract MixinShell {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
using LibRichErrorsV06 for bytes;
|
||||
|
||||
function _tradeBarter(
|
||||
function _tradeShell(
|
||||
IERC20Token sellToken,
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
(address barterRouter, bytes memory data) = abi.decode(bridgeData, (address, bytes));
|
||||
sellToken.approveIfBelow(barterRouter, sellAmount);
|
||||
IShell pool = abi.decode(bridgeData, (IShell));
|
||||
|
||||
(bool success, bytes memory resultData) = barterRouter.call(data);
|
||||
if (!success) {
|
||||
resultData.rrevert();
|
||||
}
|
||||
// Grant the Shell contract an allowance to sell the first token.
|
||||
IERC20Token(sellToken).approveIfBelow(address(pool), sellAmount);
|
||||
|
||||
return abi.decode(resultData, (uint256));
|
||||
boughtAmount = pool.originSwap(
|
||||
sellToken,
|
||||
buyToken,
|
||||
// Sell all tokens we hold.
|
||||
sellAmount,
|
||||
// Minimum buy amount.
|
||||
1,
|
||||
// deadline
|
||||
block.timestamp + 1
|
||||
);
|
||||
return boughtAmount;
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
import "../IBridgeAdapter.sol";
|
||||
|
||||
interface ILBRouter {
|
||||
/**
|
||||
* @dev This enum represents the version of the pair requested
|
||||
* - V1: Joe V1 pair
|
||||
* - V2: LB pair V2. Also called legacyPair
|
||||
* - V2_1: LB pair V2.1 (current version)
|
||||
*/
|
||||
enum Version {
|
||||
V1,
|
||||
V2,
|
||||
V2_1
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev The path parameters, such as:
|
||||
* - pairBinSteps: The list of bin steps of the pairs to go through
|
||||
* - versions: The list of versions of the pairs to go through
|
||||
* - tokenPath: The list of tokens in the path to go through
|
||||
*/
|
||||
struct Path {
|
||||
uint256[] pairBinSteps;
|
||||
Version[] versions;
|
||||
IERC20Token[] tokenPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Swaps exact tokens for tokens while performing safety checks
|
||||
* @param amountIn The amount of token to send
|
||||
* @param amountOutMin The min amount of token to receive
|
||||
* @param path The path of the swap
|
||||
* @param to The address of the recipient
|
||||
* @param deadline The deadline of the tx
|
||||
* @return amountOut Output amount of the swap
|
||||
*/
|
||||
function swapExactTokensForTokens(
|
||||
uint256 amountIn,
|
||||
uint256 amountOutMin,
|
||||
Path memory path,
|
||||
address to,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountOut);
|
||||
}
|
||||
|
||||
contract MixinTraderJoeV2 {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
|
||||
function _tradeTraderJoeV2(
|
||||
IERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
ILBRouter router;
|
||||
IERC20Token[] memory tokenPath;
|
||||
uint256[] memory pairBinSteps;
|
||||
ILBRouter.Version[] memory versions;
|
||||
{
|
||||
address[] memory _tokenPath;
|
||||
(router, _tokenPath, pairBinSteps, versions) = abi.decode(
|
||||
bridgeData,
|
||||
(ILBRouter, address[], uint256[], ILBRouter.Version[])
|
||||
);
|
||||
// To get around `abi.decode()` not supporting interface array types.
|
||||
assembly {
|
||||
tokenPath := _tokenPath
|
||||
}
|
||||
}
|
||||
|
||||
require(tokenPath.length >= 2, "MixinTraderJoeV2/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(
|
||||
tokenPath.length == pairBinSteps.length + 1,
|
||||
"MixinTraderJoeV2/PAIR_BIN_STEPS_LENGTH_MUST_BE_ONE_LESS_THAN_TOKEN_PATH_LENGTH"
|
||||
);
|
||||
require(
|
||||
versions.length == pairBinSteps.length,
|
||||
"MixinTraderJoeV2/VERSIONS_LENGTH_MUST_BE_EQUAL_TO_PAIR_BIN_STEPS_LENGTH"
|
||||
);
|
||||
require(
|
||||
tokenPath[tokenPath.length - 1] == buyToken,
|
||||
"MixinTraderJoeV2/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
|
||||
);
|
||||
// Grant the Trader Joe V2 router an allowance to sell the first token.
|
||||
tokenPath[0].approveIfBelow(address(router), sellAmount);
|
||||
|
||||
ILBRouter.Path memory path = ILBRouter.Path({
|
||||
pairBinSteps: pairBinSteps,
|
||||
versions: versions,
|
||||
tokenPath: tokenPath
|
||||
});
|
||||
boughtAmount = router.swapExactTokensForTokens(sellAmount, 1, path, address(this), block.timestamp);
|
||||
}
|
||||
}
|
@ -31,18 +31,6 @@ interface IUniswapV3Router {
|
||||
function exactInput(ExactInputParams memory params) external payable returns (uint256 amountOut);
|
||||
}
|
||||
|
||||
// https://github.com/Uniswap/swap-router-contracts/blob/main/contracts/interfaces/IV3SwapRouter.sol
|
||||
interface IUniswapV3Router2 {
|
||||
struct ExactInputParams {
|
||||
bytes path;
|
||||
address recipient;
|
||||
uint256 amountIn;
|
||||
uint256 amountOutMinimum;
|
||||
}
|
||||
|
||||
function exactInput(ExactInputParams memory params) external payable returns (uint256 amountOut);
|
||||
}
|
||||
|
||||
contract MixinUniswapV3 {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
|
||||
@ -51,30 +39,19 @@ contract MixinUniswapV3 {
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
(address router, bytes memory path, uint256 routerVersion) = abi.decode(bridgeData, (address, bytes, uint256));
|
||||
(IUniswapV3Router router, bytes memory path) = abi.decode(bridgeData, (IUniswapV3Router, bytes));
|
||||
|
||||
// Grant the Uniswap router an allowance to sell the sell token.
|
||||
sellToken.approveIfBelow(router, sellAmount);
|
||||
sellToken.approveIfBelow(address(router), sellAmount);
|
||||
|
||||
if (routerVersion != 2) {
|
||||
boughtAmount = IUniswapV3Router(router).exactInput(
|
||||
IUniswapV3Router.ExactInputParams({
|
||||
path: path,
|
||||
recipient: address(this),
|
||||
deadline: block.timestamp,
|
||||
amountIn: sellAmount,
|
||||
amountOutMinimum: 1
|
||||
})
|
||||
);
|
||||
} else {
|
||||
boughtAmount = IUniswapV3Router2(router).exactInput(
|
||||
IUniswapV3Router2.ExactInputParams({
|
||||
path: path,
|
||||
recipient: address(this),
|
||||
amountIn: sellAmount,
|
||||
amountOutMinimum: 1
|
||||
})
|
||||
);
|
||||
}
|
||||
boughtAmount = router.exactInput(
|
||||
IUniswapV3Router.ExactInputParams({
|
||||
path: path,
|
||||
recipient: address(this),
|
||||
deadline: block.timestamp,
|
||||
amountIn: sellAmount,
|
||||
amountOutMinimum: 1
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
|
||||
|
||||
interface IVelodromeV2Router {
|
||||
struct Route {
|
||||
address from;
|
||||
address to;
|
||||
bool stable;
|
||||
address factory;
|
||||
}
|
||||
|
||||
/// @notice Swap one token for another
|
||||
/// @param amountIn Amount of token in
|
||||
/// @param amountOutMin Minimum amount of desired token received
|
||||
/// @param routes Array of trade routes used in the swap
|
||||
/// @param to Recipient of the tokens received
|
||||
/// @param deadline Deadline to receive tokens
|
||||
/// @return amounts Array of amounts returned per route
|
||||
function swapExactTokensForTokens(
|
||||
uint256 amountIn,
|
||||
uint256 amountOutMin,
|
||||
Route[] calldata routes,
|
||||
address to,
|
||||
uint256 deadline
|
||||
) external returns (uint256[] memory amounts);
|
||||
}
|
||||
|
||||
contract MixinVelodromeV2 {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
|
||||
function _tradeVelodromeV2(
|
||||
IERC20Token sellToken,
|
||||
uint256 sellAmount,
|
||||
bytes memory bridgeData
|
||||
) internal returns (uint256 boughtAmount) {
|
||||
(IVelodromeV2Router router, IVelodromeV2Router.Route[] memory routes) = abi.decode(
|
||||
bridgeData,
|
||||
(IVelodromeV2Router, IVelodromeV2Router.Route[])
|
||||
);
|
||||
sellToken.approveIfBelow(address(router), sellAmount);
|
||||
|
||||
uint256[] memory amounts = router.swapExactTokensForTokens(
|
||||
sellAmount,
|
||||
1,
|
||||
routes,
|
||||
address(this),
|
||||
block.timestamp + 1
|
||||
);
|
||||
|
||||
return amounts[amounts.length - 1];
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-zero-ex",
|
||||
"version": "0.49.0",
|
||||
"version": "0.39.2",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@ -36,9 +36,9 @@
|
||||
"typechain": "typechain --target=ethers-v5 --out-dir='typechain-wrappers' './foundry-artifacts/**/*.json'"
|
||||
},
|
||||
"config": {
|
||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BaseGoerliBridgeAdapter,BaseBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter,MetaTransactionsFeatureV2",
|
||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|ArbitrumBridgeAdapter|AvalancheBridgeAdapter|BSCBridgeAdapter|BaseBridgeAdapter|BaseGoerliBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMetaTransactionsFeatureV2|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MetaTransactionsFeatureV2|MixinAaveV2|MixinBalancer|MixinBalancerV2Batch|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinSolidly|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|ArbitrumBridgeAdapter|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinSolidly|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -51,10 +51,10 @@
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.8.5",
|
||||
"@0x/contract-addresses": "^8.13.0",
|
||||
"@0x/contract-addresses": "^8.2.0",
|
||||
"@0x/contracts-erc20": "^3.3.57",
|
||||
"@0x/contracts-gen": "^2.0.50",
|
||||
"@0x/contracts-test-utils": "^5.4.60",
|
||||
"@0x/contracts-test-utils": "^5.4.50",
|
||||
"@0x/dev-utils": "^5.0.2",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-compiler": "^4.8.2",
|
||||
@ -80,7 +80,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^7.0.0",
|
||||
"@0x/protocol-utils": "^11.24.2",
|
||||
"@0x/protocol-utils": "^11.18.2",
|
||||
"@0x/subproviders": "^8.0.1",
|
||||
"@0x/types": "^3.3.7",
|
||||
"@0x/typescript-typings": "^5.3.1",
|
||||
|
@ -7,8 +7,6 @@ import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json';
|
||||
import * as AvalancheBridgeAdapter from '../generated-artifacts/AvalancheBridgeAdapter.json';
|
||||
import * as BaseBridgeAdapter from '../generated-artifacts/BaseBridgeAdapter.json';
|
||||
import * as BaseGoerliBridgeAdapter from '../generated-artifacts/BaseGoerliBridgeAdapter.json';
|
||||
import * as BatchFillNativeOrdersFeature from '../generated-artifacts/BatchFillNativeOrdersFeature.json';
|
||||
import * as BSCBridgeAdapter from '../generated-artifacts/BSCBridgeAdapter.json';
|
||||
import * as CeloBridgeAdapter from '../generated-artifacts/CeloBridgeAdapter.json';
|
||||
@ -34,7 +32,6 @@ import * as IZeroEx from '../generated-artifacts/IZeroEx.json';
|
||||
import * as LiquidityProviderFeature from '../generated-artifacts/LiquidityProviderFeature.json';
|
||||
import * as LogMetadataTransformer from '../generated-artifacts/LogMetadataTransformer.json';
|
||||
import * as MetaTransactionsFeature from '../generated-artifacts/MetaTransactionsFeature.json';
|
||||
import * as MetaTransactionsFeatureV2 from '../generated-artifacts/MetaTransactionsFeatureV2.json';
|
||||
import * as MultiplexFeature from '../generated-artifacts/MultiplexFeature.json';
|
||||
import * as NativeOrdersFeature from '../generated-artifacts/NativeOrdersFeature.json';
|
||||
import * as OptimismBridgeAdapter from '../generated-artifacts/OptimismBridgeAdapter.json';
|
||||
@ -81,13 +78,10 @@ export const artifacts = {
|
||||
OtcOrdersFeature: OtcOrdersFeature as ContractArtifact,
|
||||
IOtcOrdersFeature: IOtcOrdersFeature as ContractArtifact,
|
||||
AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact,
|
||||
BaseGoerliBridgeAdapter: BaseGoerliBridgeAdapter as ContractArtifact,
|
||||
BaseBridgeAdapter: BaseBridgeAdapter as ContractArtifact,
|
||||
BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact,
|
||||
CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact,
|
||||
EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact,
|
||||
FantomBridgeAdapter: FantomBridgeAdapter as ContractArtifact,
|
||||
OptimismBridgeAdapter: OptimismBridgeAdapter as ContractArtifact,
|
||||
PolygonBridgeAdapter: PolygonBridgeAdapter as ContractArtifact,
|
||||
MetaTransactionsFeatureV2: MetaTransactionsFeatureV2 as ContractArtifact,
|
||||
};
|
||||
|
@ -1,34 +1,3 @@
|
||||
export { ZeroExRevertErrors } from '@0x/utils';
|
||||
export {
|
||||
AbiDefinition,
|
||||
CompilerOpts,
|
||||
CompilerSettings,
|
||||
CompilerSettingsMetadata,
|
||||
ConstructorAbi,
|
||||
ConstructorStateMutability,
|
||||
ContractAbi,
|
||||
ContractArtifact,
|
||||
ContractChainData,
|
||||
ContractChains,
|
||||
DataItem,
|
||||
DevdocOutput,
|
||||
EventAbi,
|
||||
EventParameter,
|
||||
EvmBytecodeOutput,
|
||||
EvmBytecodeOutputLinkReferences,
|
||||
EvmOutput,
|
||||
FallbackAbi,
|
||||
FunctionAbi,
|
||||
MethodAbi,
|
||||
OptimizerSettings,
|
||||
OutputField,
|
||||
ParamDescription,
|
||||
RevertErrorAbi,
|
||||
StandardContractOutput,
|
||||
StateMutability,
|
||||
SupportedProvider,
|
||||
TupleDataItem,
|
||||
} from 'ethereum-types';
|
||||
export { artifacts } from './artifacts';
|
||||
export * from './migration';
|
||||
export * from './nonce_utils';
|
||||
@ -58,4 +27,3 @@ export {
|
||||
WethTransformerContract,
|
||||
ZeroExContract,
|
||||
} from './wrappers';
|
||||
export { EIP712TypedData } from '@0x/types';
|
||||
|
@ -6,8 +6,6 @@
|
||||
export * from '../generated-wrappers/affiliate_fee_transformer';
|
||||
export * from '../generated-wrappers/avalanche_bridge_adapter';
|
||||
export * from '../generated-wrappers/b_s_c_bridge_adapter';
|
||||
export * from '../generated-wrappers/base_bridge_adapter';
|
||||
export * from '../generated-wrappers/base_goerli_bridge_adapter';
|
||||
export * from '../generated-wrappers/batch_fill_native_orders_feature';
|
||||
export * from '../generated-wrappers/celo_bridge_adapter';
|
||||
export * from '../generated-wrappers/curve_liquidity_provider';
|
||||
@ -32,7 +30,6 @@ export * from '../generated-wrappers/initial_migration';
|
||||
export * from '../generated-wrappers/liquidity_provider_feature';
|
||||
export * from '../generated-wrappers/log_metadata_transformer';
|
||||
export * from '../generated-wrappers/meta_transactions_feature';
|
||||
export * from '../generated-wrappers/meta_transactions_feature_v2';
|
||||
export * from '../generated-wrappers/multiplex_feature';
|
||||
export * from '../generated-wrappers/native_orders_feature';
|
||||
export * from '../generated-wrappers/optimism_bridge_adapter';
|
||||
|
@ -9,8 +9,6 @@ import * as AbstractBridgeAdapter from '../test/generated-artifacts/AbstractBrid
|
||||
import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json';
|
||||
import * as ArbitrumBridgeAdapter from '../test/generated-artifacts/ArbitrumBridgeAdapter.json';
|
||||
import * as AvalancheBridgeAdapter from '../test/generated-artifacts/AvalancheBridgeAdapter.json';
|
||||
import * as BaseBridgeAdapter from '../test/generated-artifacts/BaseBridgeAdapter.json';
|
||||
import * as BaseGoerliBridgeAdapter from '../test/generated-artifacts/BaseGoerliBridgeAdapter.json';
|
||||
import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json';
|
||||
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
|
||||
import * as BridgeProtocols from '../test/generated-artifacts/BridgeProtocols.json';
|
||||
@ -53,7 +51,6 @@ import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvi
|
||||
import * as ILiquidityProviderFeature from '../test/generated-artifacts/ILiquidityProviderFeature.json';
|
||||
import * as ILiquidityProviderSandbox from '../test/generated-artifacts/ILiquidityProviderSandbox.json';
|
||||
import * as IMetaTransactionsFeature from '../test/generated-artifacts/IMetaTransactionsFeature.json';
|
||||
import * as IMetaTransactionsFeatureV2 from '../test/generated-artifacts/IMetaTransactionsFeatureV2.json';
|
||||
import * as IMooniswapPool from '../test/generated-artifacts/IMooniswapPool.json';
|
||||
import * as IMultiplexFeature from '../test/generated-artifacts/IMultiplexFeature.json';
|
||||
import * as INativeOrdersEvents from '../test/generated-artifacts/INativeOrdersEvents.json';
|
||||
@ -107,10 +104,10 @@ import * as LiquidityProviderFeature from '../test/generated-artifacts/Liquidity
|
||||
import * as LiquidityProviderSandbox from '../test/generated-artifacts/LiquidityProviderSandbox.json';
|
||||
import * as LogMetadataTransformer from '../test/generated-artifacts/LogMetadataTransformer.json';
|
||||
import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransactionsFeature.json';
|
||||
import * as MetaTransactionsFeatureV2 from '../test/generated-artifacts/MetaTransactionsFeatureV2.json';
|
||||
import * as MixinAaveV2 from '../test/generated-artifacts/MixinAaveV2.json';
|
||||
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
|
||||
import * as MixinBalancerV2Batch from '../test/generated-artifacts/MixinBalancerV2Batch.json';
|
||||
import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json';
|
||||
import * as MixinBancorV3 from '../test/generated-artifacts/MixinBancorV3.json';
|
||||
import * as MixinCompound from '../test/generated-artifacts/MixinCompound.json';
|
||||
import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json';
|
||||
@ -123,8 +120,10 @@ import * as MixinKyberDmm from '../test/generated-artifacts/MixinKyberDmm.json';
|
||||
import * as MixinLido from '../test/generated-artifacts/MixinLido.json';
|
||||
import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json';
|
||||
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
|
||||
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
|
||||
import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json';
|
||||
import * as MixinPlatypus from '../test/generated-artifacts/MixinPlatypus.json';
|
||||
import * as MixinShell from '../test/generated-artifacts/MixinShell.json';
|
||||
import * as MixinSolidly from '../test/generated-artifacts/MixinSolidly.json';
|
||||
import * as MixinSynthetix from '../test/generated-artifacts/MixinSynthetix.json';
|
||||
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
|
||||
@ -237,7 +236,6 @@ export const artifacts = {
|
||||
FundRecoveryFeature: FundRecoveryFeature as ContractArtifact,
|
||||
LiquidityProviderFeature: LiquidityProviderFeature as ContractArtifact,
|
||||
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
|
||||
MetaTransactionsFeatureV2: MetaTransactionsFeatureV2 as ContractArtifact,
|
||||
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
|
||||
OtcOrdersFeature: OtcOrdersFeature as ContractArtifact,
|
||||
OwnableFeature: OwnableFeature as ContractArtifact,
|
||||
@ -255,7 +253,6 @@ export const artifacts = {
|
||||
IFundRecoveryFeature: IFundRecoveryFeature as ContractArtifact,
|
||||
ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact,
|
||||
IMetaTransactionsFeature: IMetaTransactionsFeature as ContractArtifact,
|
||||
IMetaTransactionsFeatureV2: IMetaTransactionsFeatureV2 as ContractArtifact,
|
||||
IMultiplexFeature: IMultiplexFeature as ContractArtifact,
|
||||
INativeOrdersEvents: INativeOrdersEvents as ContractArtifact,
|
||||
INativeOrdersFeature: INativeOrdersFeature as ContractArtifact,
|
||||
@ -321,8 +318,6 @@ export const artifacts = {
|
||||
ArbitrumBridgeAdapter: ArbitrumBridgeAdapter as ContractArtifact,
|
||||
AvalancheBridgeAdapter: AvalancheBridgeAdapter as ContractArtifact,
|
||||
BSCBridgeAdapter: BSCBridgeAdapter as ContractArtifact,
|
||||
BaseBridgeAdapter: BaseBridgeAdapter as ContractArtifact,
|
||||
BaseGoerliBridgeAdapter: BaseGoerliBridgeAdapter as ContractArtifact,
|
||||
BridgeProtocols: BridgeProtocols as ContractArtifact,
|
||||
CeloBridgeAdapter: CeloBridgeAdapter as ContractArtifact,
|
||||
EthereumBridgeAdapter: EthereumBridgeAdapter as ContractArtifact,
|
||||
@ -333,6 +328,7 @@ export const artifacts = {
|
||||
MixinAaveV2: MixinAaveV2 as ContractArtifact,
|
||||
MixinBalancer: MixinBalancer as ContractArtifact,
|
||||
MixinBalancerV2Batch: MixinBalancerV2Batch as ContractArtifact,
|
||||
MixinBancor: MixinBancor as ContractArtifact,
|
||||
MixinBancorV3: MixinBancorV3 as ContractArtifact,
|
||||
MixinCompound: MixinCompound as ContractArtifact,
|
||||
MixinCryptoCom: MixinCryptoCom as ContractArtifact,
|
||||
@ -343,10 +339,12 @@ export const artifacts = {
|
||||
MixinGMX: MixinGMX as ContractArtifact,
|
||||
MixinKyberDmm: MixinKyberDmm as ContractArtifact,
|
||||
MixinLido: MixinLido as ContractArtifact,
|
||||
MixinMStable: MixinMStable as ContractArtifact,
|
||||
MixinMakerPSM: MixinMakerPSM as ContractArtifact,
|
||||
MixinMooniswap: MixinMooniswap as ContractArtifact,
|
||||
MixinNerve: MixinNerve as ContractArtifact,
|
||||
MixinPlatypus: MixinPlatypus as ContractArtifact,
|
||||
MixinShell: MixinShell as ContractArtifact,
|
||||
MixinSolidly: MixinSolidly as ContractArtifact,
|
||||
MixinSynthetix: MixinSynthetix as ContractArtifact,
|
||||
MixinUniswap: MixinUniswap as ContractArtifact,
|
||||
|
@ -8,8 +8,6 @@ export * from '../test/generated-wrappers/affiliate_fee_transformer';
|
||||
export * from '../test/generated-wrappers/arbitrum_bridge_adapter';
|
||||
export * from '../test/generated-wrappers/avalanche_bridge_adapter';
|
||||
export * from '../test/generated-wrappers/b_s_c_bridge_adapter';
|
||||
export * from '../test/generated-wrappers/base_bridge_adapter';
|
||||
export * from '../test/generated-wrappers/base_goerli_bridge_adapter';
|
||||
export * from '../test/generated-wrappers/batch_fill_native_orders_feature';
|
||||
export * from '../test/generated-wrappers/bootstrap_feature';
|
||||
export * from '../test/generated-wrappers/bridge_protocols';
|
||||
@ -51,7 +49,6 @@ export * from '../test/generated-wrappers/i_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_feature';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_sandbox';
|
||||
export * from '../test/generated-wrappers/i_meta_transactions_feature';
|
||||
export * from '../test/generated-wrappers/i_meta_transactions_feature_v2';
|
||||
export * from '../test/generated-wrappers/i_mooniswap_pool';
|
||||
export * from '../test/generated-wrappers/i_multiplex_feature';
|
||||
export * from '../test/generated-wrappers/i_native_orders_events';
|
||||
@ -105,10 +102,10 @@ export * from '../test/generated-wrappers/liquidity_provider_feature';
|
||||
export * from '../test/generated-wrappers/liquidity_provider_sandbox';
|
||||
export * from '../test/generated-wrappers/log_metadata_transformer';
|
||||
export * from '../test/generated-wrappers/meta_transactions_feature';
|
||||
export * from '../test/generated-wrappers/meta_transactions_feature_v2';
|
||||
export * from '../test/generated-wrappers/mixin_aave_v2';
|
||||
export * from '../test/generated-wrappers/mixin_balancer';
|
||||
export * from '../test/generated-wrappers/mixin_balancer_v2_batch';
|
||||
export * from '../test/generated-wrappers/mixin_bancor';
|
||||
export * from '../test/generated-wrappers/mixin_bancor_v3';
|
||||
export * from '../test/generated-wrappers/mixin_compound';
|
||||
export * from '../test/generated-wrappers/mixin_crypto_com';
|
||||
@ -119,10 +116,12 @@ export * from '../test/generated-wrappers/mixin_dodo_v2';
|
||||
export * from '../test/generated-wrappers/mixin_g_m_x';
|
||||
export * from '../test/generated-wrappers/mixin_kyber_dmm';
|
||||
export * from '../test/generated-wrappers/mixin_lido';
|
||||
export * from '../test/generated-wrappers/mixin_m_stable';
|
||||
export * from '../test/generated-wrappers/mixin_maker_p_s_m';
|
||||
export * from '../test/generated-wrappers/mixin_mooniswap';
|
||||
export * from '../test/generated-wrappers/mixin_nerve';
|
||||
export * from '../test/generated-wrappers/mixin_platypus';
|
||||
export * from '../test/generated-wrappers/mixin_shell';
|
||||
export * from '../test/generated-wrappers/mixin_solidly';
|
||||
export * from '../test/generated-wrappers/mixin_synthetix';
|
||||
export * from '../test/generated-wrappers/mixin_uniswap';
|
||||
|
@ -1,496 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./utils/BaseTest.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "./utils/LocalTest.sol";
|
||||
import "../contracts/src/features/MetaTransactionsFeatureV2.sol";
|
||||
import "../contracts/src/features/interfaces/IMetaTransactionsFeatureV2.sol";
|
||||
import "../contracts/src/features/interfaces/IMetaTransactionsFeature.sol";
|
||||
import "../contracts/test/TestMintTokenERC20Transformer.sol";
|
||||
import "../contracts/src/features/libs/LibSignature.sol";
|
||||
import "src/features/libs/LibNativeOrder.sol";
|
||||
import "../contracts/test/tokens/TestMintableERC20Token.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
|
||||
|
||||
contract MetaTransactionTest is LocalTest {
|
||||
address private constant USER_ADDRESS = 0x6dc3a54FeAE57B65d185A7B159c5d3FA7fD7FD0F;
|
||||
uint256 private constant USER_KEY = 0x1fc1630343b31e60b7a197a53149ca571ed9d9791e2833337bbd8110c30710ec;
|
||||
|
||||
event MetaTransactionExecuted(bytes32 hash, bytes4 indexed selector, address signer, address sender);
|
||||
|
||||
function _mtxSignature(
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx
|
||||
) private returns (LibSignature.Signature memory) {
|
||||
return _mtxSignatureWithSignerKey(mtx, USER_KEY);
|
||||
}
|
||||
|
||||
function _mtxSignatureWithSignerKey(
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx,
|
||||
uint256 key
|
||||
) private returns (LibSignature.Signature memory) {
|
||||
// Mint fee to signer and approve
|
||||
for (uint256 i = 0; i < mtx.fees.length; ++i) {
|
||||
_mintTo(address(weth), mtx.signer, mtx.fees[i].amount);
|
||||
}
|
||||
vm.prank(mtx.signer);
|
||||
mtx.feeToken.approve(address(zeroExDeployed.zeroEx), 1e18);
|
||||
|
||||
bytes32 mtxHash = zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtx);
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(key, mtxHash);
|
||||
LibSignature.Signature memory sig = LibSignature.Signature(LibSignature.SignatureType.EIP712, v, r, s);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
function _getMetaTransaction(
|
||||
bytes memory callData
|
||||
) private view returns (IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory) {
|
||||
IMetaTransactionsFeatureV2.MetaTransactionFeeData[]
|
||||
memory fees = new IMetaTransactionsFeatureV2.MetaTransactionFeeData[](1);
|
||||
fees[0] = IMetaTransactionsFeatureV2.MetaTransactionFeeData({recipient: address(this), amount: 1});
|
||||
return _getMetaTransactionWithFees(callData, fees);
|
||||
}
|
||||
|
||||
function _getMetaTransactionWithFees(
|
||||
bytes memory callData,
|
||||
IMetaTransactionsFeatureV2.MetaTransactionFeeData[] memory fees
|
||||
) private view returns (IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory) {
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx = IMetaTransactionsFeatureV2.MetaTransactionDataV2({
|
||||
signer: payable(USER_ADDRESS),
|
||||
sender: address(this),
|
||||
expirationTimeSeconds: block.timestamp + 60,
|
||||
salt: 123,
|
||||
callData: callData,
|
||||
feeToken: weth,
|
||||
fees: fees
|
||||
});
|
||||
return mtx;
|
||||
}
|
||||
|
||||
function _badSelectorTransformERC20Call() private pure returns (bytes memory) {
|
||||
return abi.encodeWithSelector(ITransformERC20Feature.createTransformWallet.selector);
|
||||
}
|
||||
|
||||
function _badTokenTransformERC20Call() private returns (bytes memory) {
|
||||
ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](1);
|
||||
transformations[0] = ITransformERC20Feature.Transformation(
|
||||
uint32(transformerNonce),
|
||||
abi.encode(address(dai), address(weth), 0, 1e18, 0)
|
||||
);
|
||||
|
||||
_mintTo(address(dai), USER_ADDRESS, 1e18);
|
||||
vm.prank(USER_ADDRESS);
|
||||
dai.approve(address(zeroExDeployed.zeroEx), 1e18);
|
||||
|
||||
return
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.transformERC20.selector, // 0x415565b0
|
||||
dai,
|
||||
weth,
|
||||
1e18,
|
||||
1e18,
|
||||
transformations
|
||||
);
|
||||
}
|
||||
|
||||
function _makeTestRfqOrder(
|
||||
IERC20Token makerToken,
|
||||
IERC20Token takerToken,
|
||||
address makerAddress,
|
||||
address takerAddress,
|
||||
uint256 makerKey
|
||||
) internal returns (bytes memory callData) {
|
||||
LibNativeOrder.RfqOrder memory order = LibNativeOrder.RfqOrder({
|
||||
makerToken: makerToken,
|
||||
takerToken: takerToken,
|
||||
makerAmount: 1e18,
|
||||
takerAmount: 1e18,
|
||||
maker: makerAddress,
|
||||
taker: address(0),
|
||||
txOrigin: tx.origin,
|
||||
pool: 0x0000000000000000000000000000000000000000000000000000000000000000,
|
||||
expiry: uint64(block.timestamp + 60),
|
||||
salt: 123
|
||||
});
|
||||
_mintTo(address(order.makerToken), order.maker, order.makerAmount);
|
||||
vm.prank(order.maker);
|
||||
order.makerToken.approve(address(zeroExDeployed.zeroEx), order.makerAmount);
|
||||
_mintTo(address(order.takerToken), takerAddress, order.takerAmount);
|
||||
vm.prank(takerAddress);
|
||||
order.takerToken.approve(address(zeroExDeployed.zeroEx), order.takerAmount);
|
||||
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
|
||||
makerKey,
|
||||
zeroExDeployed.features.nativeOrdersFeature.getRfqOrderHash(order)
|
||||
);
|
||||
LibSignature.Signature memory sig = LibSignature.Signature(LibSignature.SignatureType.EIP712, v, r, s);
|
||||
|
||||
return
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature.fillRfqOrder.selector, // 0xaa77476c
|
||||
order, // RFQOrder
|
||||
sig, // Order Signature
|
||||
1e18 // Fill Amount
|
||||
);
|
||||
}
|
||||
|
||||
function _makeTestLimitOrder(
|
||||
IERC20Token makerToken,
|
||||
IERC20Token takerToken,
|
||||
address makerAddress,
|
||||
address takerAddress,
|
||||
uint256 makerKey
|
||||
) internal returns (bytes memory callData) {
|
||||
LibNativeOrder.LimitOrder memory order = LibNativeOrder.LimitOrder({
|
||||
makerToken: makerToken,
|
||||
takerToken: takerToken,
|
||||
makerAmount: 1e18,
|
||||
takerAmount: 1e18,
|
||||
maker: makerAddress,
|
||||
taker: address(0),
|
||||
sender: address(0),
|
||||
takerTokenFeeAmount: 0,
|
||||
feeRecipient: address(0),
|
||||
pool: 0x0000000000000000000000000000000000000000000000000000000000000000,
|
||||
expiry: uint64(block.timestamp + 60),
|
||||
salt: 123
|
||||
});
|
||||
_mintTo(address(order.makerToken), order.maker, order.makerAmount);
|
||||
vm.prank(order.maker);
|
||||
order.makerToken.approve(address(zeroExDeployed.zeroEx), order.makerAmount);
|
||||
_mintTo(address(order.takerToken), takerAddress, order.takerAmount);
|
||||
vm.prank(takerAddress);
|
||||
order.takerToken.approve(address(zeroExDeployed.zeroEx), order.takerAmount);
|
||||
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
|
||||
makerKey,
|
||||
zeroExDeployed.features.nativeOrdersFeature.getLimitOrderHash(order)
|
||||
);
|
||||
LibSignature.Signature memory sig = LibSignature.Signature(LibSignature.SignatureType.EIP712, v, r, s);
|
||||
|
||||
return
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature.fillLimitOrder.selector, // 0xf6274f66
|
||||
order, // LimitOrder
|
||||
sig, // Order Signature
|
||||
1e18 // Fill Amount
|
||||
);
|
||||
}
|
||||
|
||||
function _transformERC20Call(
|
||||
IERC20Token makerToken,
|
||||
IERC20Token takerToken,
|
||||
address takerAddress
|
||||
) internal returns (bytes memory) {
|
||||
ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](1);
|
||||
transformations[0] = ITransformERC20Feature.Transformation(
|
||||
uint32(transformerNonce),
|
||||
abi.encode(address(takerToken), address(makerToken), 0, 1e18, 0)
|
||||
);
|
||||
|
||||
_mintTo(address(takerToken), takerAddress, 1e18);
|
||||
vm.prank(takerAddress);
|
||||
takerToken.approve(address(zeroExDeployed.zeroEx), 1e18);
|
||||
|
||||
return
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.transformERC20.selector, // 0x415565b0
|
||||
takerToken,
|
||||
makerToken,
|
||||
1e18,
|
||||
1e18,
|
||||
transformations
|
||||
);
|
||||
}
|
||||
|
||||
function test_createHash() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
|
||||
bytes32 mtxHash = zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtxData);
|
||||
assertTrue(mtxHash != bytes32(0));
|
||||
}
|
||||
|
||||
function test_EIP_712_signature() external {
|
||||
// metamask wallet signed data
|
||||
bytes32 r_mm = 0xcd6c09d558e23803afae870ca53a8e7bfaf5564c64ee29f23dc4a19e7dd9e9b5;
|
||||
bytes32 s_mm = 0x1ae68e89fadab4a7f4d01fd5543e5e0efd5697e87c993f045f671aba3e1f55ac;
|
||||
uint8 v_mm = 0x1b;
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionFeeData[]
|
||||
memory fees = new IMetaTransactionsFeatureV2.MetaTransactionFeeData[](2);
|
||||
fees[0] = IMetaTransactionsFeatureV2.MetaTransactionFeeData({recipient: address(0), amount: 1000000});
|
||||
fees[1] = IMetaTransactionsFeatureV2.MetaTransactionFeeData({recipient: address(0), amount: 1000});
|
||||
IERC20Token usdcToken = IERC20Token(address(0x2e234DAe75C793f67A35089C9d99245E1C58470b));
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx = IMetaTransactionsFeatureV2.MetaTransactionDataV2({
|
||||
signer: address(0),
|
||||
sender: address(0),
|
||||
expirationTimeSeconds: 99999999,
|
||||
salt: 1234,
|
||||
callData: new bytes(0),
|
||||
feeToken: usdcToken,
|
||||
fees: fees
|
||||
});
|
||||
|
||||
bytes32 mtxHash = zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtx);
|
||||
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(USER_KEY, mtxHash);
|
||||
//emit log_bytes(abi.encodePacked(r, s, bytes1(v)));
|
||||
|
||||
// Verify signature matches from what we generated using metamask
|
||||
assertTrue(v == v_mm);
|
||||
assertTrue(r == r_mm);
|
||||
assertTrue(s == s_mm);
|
||||
}
|
||||
|
||||
function test_transformERC20() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
vm.expectEmit(true, false, false, true);
|
||||
emit MetaTransactionExecuted(
|
||||
zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtxData),
|
||||
zeroExDeployed.zeroEx.transformERC20.selector, // 0x415565b0
|
||||
USER_ADDRESS,
|
||||
address(this)
|
||||
);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(weth.balanceOf(address(this)), 1);
|
||||
}
|
||||
|
||||
function test_rfqOrder() external {
|
||||
bytes memory callData = _makeTestRfqOrder(zrx, dai, signerAddress, USER_ADDRESS, signerKey);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(callData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
vm.expectEmit(true, false, false, true);
|
||||
emit MetaTransactionExecuted(
|
||||
zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtxData),
|
||||
INativeOrdersFeature.fillRfqOrder.selector, // 0xaa77476c
|
||||
USER_ADDRESS,
|
||||
address(this)
|
||||
);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
|
||||
assertEq(zrx.balanceOf(signerAddress), 0);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(dai.balanceOf(signerAddress), 1e18);
|
||||
assertEq(weth.balanceOf(address(this)), 1);
|
||||
}
|
||||
|
||||
function test_fillLimitOrder() external {
|
||||
bytes memory callData = _makeTestLimitOrder(zrx, dai, signerAddress, USER_ADDRESS, signerKey);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(callData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
vm.expectEmit(true, false, false, true);
|
||||
emit MetaTransactionExecuted(
|
||||
zeroExDeployed.features.metaTransactionsFeatureV2.getMetaTransactionV2Hash(mtxData),
|
||||
INativeOrdersFeature.fillLimitOrder.selector, // 0xf6274f66
|
||||
USER_ADDRESS,
|
||||
address(this)
|
||||
);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
|
||||
assertEq(zrx.balanceOf(signerAddress), 0);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(dai.balanceOf(signerAddress), 1e18);
|
||||
assertEq(weth.balanceOf(address(this)), 1);
|
||||
}
|
||||
|
||||
function test_transformERC20WithAnySender() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
mtxData.sender = address(0);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(
|
||||
mtxData,
|
||||
_mtxSignature(mtxData)
|
||||
);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(weth.balanceOf(address(this)), 1);
|
||||
}
|
||||
|
||||
function test_transformERC20WithoutFee() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionFeeData[] memory fees;
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransactionWithFees(
|
||||
transformCallData,
|
||||
fees
|
||||
);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(
|
||||
mtxData,
|
||||
_mtxSignature(mtxData)
|
||||
);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(weth.balanceOf(address(this)), 0); // no fee paid out
|
||||
}
|
||||
|
||||
function test_transformERC20MultipleFees() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionFeeData[]
|
||||
memory fees = new IMetaTransactionsFeatureV2.MetaTransactionFeeData[](2);
|
||||
fees[0] = IMetaTransactionsFeatureV2.MetaTransactionFeeData({recipient: address(this), amount: 10});
|
||||
fees[1] = IMetaTransactionsFeatureV2.MetaTransactionFeeData({recipient: signerAddress, amount: 20});
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransactionWithFees(
|
||||
transformCallData,
|
||||
fees
|
||||
);
|
||||
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 1e18);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(
|
||||
mtxData,
|
||||
_mtxSignature(mtxData)
|
||||
);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 1e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(weth.balanceOf(address(this)), 10);
|
||||
assertEq(weth.balanceOf(address(signerAddress)), 20);
|
||||
}
|
||||
|
||||
function test_transformERC20TranslatedCallFail() external {
|
||||
bytes memory transformCallData = _badTokenTransformERC20Call();
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_transformERC20UnsupportedFunction() external {
|
||||
bytes memory transformCallData = _badSelectorTransformERC20Call();
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_transformERC20CantExecuteTwice() external {
|
||||
bytes memory callData = _makeTestRfqOrder(zrx, dai, signerAddress, USER_ADDRESS, signerKey);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(callData);
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_metaTxnFailsIfExpired() external {
|
||||
bytes memory callData = _makeTestRfqOrder(zrx, dai, signerAddress, USER_ADDRESS, signerKey);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(callData);
|
||||
mtxData.expirationTimeSeconds = block.timestamp - 1;
|
||||
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_metaTxnFailsIfWrongSender() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
mtxData.sender = USER_ADDRESS;
|
||||
|
||||
LibSignature.Signature memory sig = _mtxSignature(mtxData);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_metaTxnFailsWrongSignature() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtxData = _getMetaTransaction(transformCallData);
|
||||
|
||||
LibSignature.Signature memory sig = _mtxSignatureWithSignerKey(mtxData, signerKey);
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).executeMetaTransactionV2(mtxData, sig);
|
||||
}
|
||||
|
||||
function test_batchExecuteMetaTransactionsMultipleTransactions() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
bytes memory rfqCallData = _makeTestRfqOrder(zrx, shib, signerAddress, USER_ADDRESS, signerKey);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2[]
|
||||
memory mtxns = new IMetaTransactionsFeatureV2.MetaTransactionDataV2[](2);
|
||||
LibSignature.Signature[] memory sigs = new LibSignature.Signature[](2);
|
||||
|
||||
mtxns[0] = _getMetaTransaction(transformCallData);
|
||||
sigs[0] = _mtxSignature(mtxns[0]);
|
||||
mtxns[1] = _getMetaTransaction(rfqCallData);
|
||||
sigs[1] = _mtxSignature(mtxns[1]);
|
||||
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).batchExecuteMetaTransactionsV2(mtxns, sigs);
|
||||
assertEq(zrx.balanceOf(USER_ADDRESS), 2e18);
|
||||
assertEq(dai.balanceOf(USER_ADDRESS), 0);
|
||||
assertEq(shib.balanceOf(USER_ADDRESS), 0);
|
||||
}
|
||||
|
||||
function test_batchExecuteMetaTransactionsCantExecuteSameTxnTwice() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2[]
|
||||
memory mtxns = new IMetaTransactionsFeatureV2.MetaTransactionDataV2[](2);
|
||||
LibSignature.Signature[] memory sigs = new LibSignature.Signature[](2);
|
||||
|
||||
mtxns[0] = _getMetaTransaction(transformCallData);
|
||||
sigs[0] = _mtxSignature(mtxns[0]);
|
||||
mtxns[1] = mtxns[0];
|
||||
sigs[1] = _mtxSignature(mtxns[1]);
|
||||
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).batchExecuteMetaTransactionsV2(mtxns, sigs);
|
||||
}
|
||||
|
||||
function test_batchExecuteMetaTransactionsFailsIfTransactionFails() external {
|
||||
bytes memory transformCallData = _transformERC20Call(zrx, dai, USER_ADDRESS);
|
||||
bytes memory badTransformCallData = _badTokenTransformERC20Call();
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2[]
|
||||
memory mtxns = new IMetaTransactionsFeatureV2.MetaTransactionDataV2[](2);
|
||||
LibSignature.Signature[] memory sigs = new LibSignature.Signature[](2);
|
||||
|
||||
mtxns[0] = _getMetaTransaction(transformCallData);
|
||||
sigs[0] = _mtxSignature(mtxns[0]);
|
||||
mtxns[1] = _getMetaTransaction(badTransformCallData);
|
||||
sigs[1] = _mtxSignature(mtxns[1]);
|
||||
|
||||
vm.expectRevert();
|
||||
IMetaTransactionsFeatureV2(address(zeroExDeployed.zeroEx)).batchExecuteMetaTransactionsV2(mtxns, sigs);
|
||||
}
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pragma solidity ^0.6;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {LocalTest} from "utils/LocalTest.sol";
|
||||
import {MultiplexUtils} from "utils/MultiplexUtils.sol";
|
||||
import {LibSignature} from "src/features/libs/LibSignature.sol";
|
||||
import {LibNativeOrder} from "src/features/libs/LibNativeOrder.sol";
|
||||
import {IMetaTransactionsFeatureV2} from "src/features/interfaces/IMetaTransactionsFeatureV2.sol";
|
||||
|
||||
contract MultiplexMetaTransactionsV2 is LocalTest, MultiplexUtils {
|
||||
function _makeMetaTransactionV2(
|
||||
bytes memory callData
|
||||
) private view returns (IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory, LibSignature.Signature memory) {
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx = IMetaTransactionsFeatureV2.MetaTransactionDataV2({
|
||||
signer: payable(otherSignerAddress),
|
||||
sender: address(0),
|
||||
expirationTimeSeconds: block.timestamp + 600,
|
||||
salt: 123,
|
||||
callData: callData,
|
||||
feeToken: dai,
|
||||
fees: new IMetaTransactionsFeatureV2.MetaTransactionFeeData[](0)
|
||||
});
|
||||
|
||||
bytes32 mtxHash = zeroExDeployed.zeroEx.getMetaTransactionV2Hash(mtx);
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(otherSignerKey, mtxHash);
|
||||
LibSignature.Signature memory sig = LibSignature.Signature(LibSignature.SignatureType.EIP712, v, r, s);
|
||||
|
||||
return (mtx, sig);
|
||||
}
|
||||
|
||||
function _executeMetaTransaction(bytes memory callData) private {
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx;
|
||||
LibSignature.Signature memory sig;
|
||||
(mtx, sig) = _makeMetaTransactionV2(callData);
|
||||
zeroExDeployed.zeroEx.executeMetaTransactionV2(mtx, sig);
|
||||
}
|
||||
|
||||
// batch
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_rfqOrder() external {
|
||||
LibNativeOrder.RfqOrder memory rfqOrder = _makeTestRfqOrder();
|
||||
rfqOrder.taker = otherSignerAddress;
|
||||
_mintTo(address(rfqOrder.takerToken), otherSignerAddress, rfqOrder.takerAmount);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeRfqSubcall(rfqOrder)),
|
||||
rfqOrder.takerAmount,
|
||||
rfqOrder.makerAmount
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_otcOrder() external {
|
||||
LibNativeOrder.OtcOrder memory otcOrder = _makeTestOtcOrder();
|
||||
otcOrder.taker = otherSignerAddress;
|
||||
_mintTo(address(otcOrder.takerToken), otherSignerAddress, otcOrder.takerAmount);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeOtcSubcall(otcOrder)),
|
||||
otcOrder.takerAmount,
|
||||
otcOrder.makerAmount
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_uniswapV2() external {
|
||||
_createUniswapV2Pool(uniV2Factory, dai, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeUniswapV2BatchSubcall(_makeArray(address(dai), address(zrx)), 1e18, false)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_uniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(zrx)), 1e18)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_liquidityProvider() external {
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
_mintTo(address(zrx), address(liquidityProvider), 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeMockLiquidityProviderBatchSubcall(1e18)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_transformErc20() external {
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeMockTransformERC20Subcall(dai, zrx, 1e18, 1e18)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_rfqOrderUniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
LibNativeOrder.RfqOrder memory rfqOrder = _makeTestRfqOrder();
|
||||
rfqOrder.taker = otherSignerAddress;
|
||||
_mintTo(address(dai), otherSignerAddress, 2e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(
|
||||
_makeRfqSubcall(rfqOrder),
|
||||
_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(zrx)), 1e18)
|
||||
),
|
||||
2e18,
|
||||
11e18
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_rfqOrderFallbackUniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 2e18);
|
||||
LibNativeOrder.RfqOrder memory rfqOrder = _makeTestRfqOrder();
|
||||
rfqOrder.taker = otherSignerAddress;
|
||||
rfqOrder.expiry = 1;
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(
|
||||
_makeRfqSubcall(rfqOrder),
|
||||
_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(zrx)), 1e18)
|
||||
),
|
||||
1e18,
|
||||
10e18
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_uniswapV3_revertsIfIncorrectAmount() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx;
|
||||
LibSignature.Signature memory sig;
|
||||
(mtx, sig) = _makeMetaTransactionV2(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(zrx)), 5e17)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
|
||||
vm.expectRevert();
|
||||
zeroExDeployed.zeroEx.executeMetaTransactionV2(mtx, sig);
|
||||
}
|
||||
|
||||
// multi hop
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForToken_uniswapV2() external {
|
||||
_createUniswapV2Pool(uniV2Factory, dai, zrx, 10e18, 10e18);
|
||||
address[] memory tokens = _makeArray(address(dai), address(zrx));
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
tokens,
|
||||
_makeArray(_makeUniswapV2MultiHopSubcall(tokens, false)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForToken_uniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
address[] memory tokens = _makeArray(address(dai), address(zrx));
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
tokens,
|
||||
_makeArray(_makeUniswapV3MultiHopSubcall(tokens)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForToken_liquidityProvider() external {
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
_mintTo(address(zrx), address(liquidityProvider), 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
_makeArray(address(dai), address(zrx)),
|
||||
_makeArray(_makeMockLiquidityProviderMultiHopSubcall()),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForToken_uniswapV2UniswapV3() external {
|
||||
_createUniswapV2Pool(uniV2Factory, dai, shib, 10e18, 10e18);
|
||||
_createUniswapV3Pool(uniV3Factory, shib, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
_makeArray(address(dai), address(shib), address(zrx)),
|
||||
_makeArray(
|
||||
_makeUniswapV2MultiHopSubcall(_makeArray(address(dai), address(shib)), false),
|
||||
_makeUniswapV3MultiHopSubcall(_makeArray(address(shib), address(zrx)))
|
||||
),
|
||||
1e18,
|
||||
10e18
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// batch for eth
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForEth_uniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, weth, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForEth.selector,
|
||||
dai,
|
||||
_makeArray(_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(weth)), 1e18)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForEth_rfqOrderUniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, weth, 10e18, 10e18);
|
||||
LibNativeOrder.RfqOrder memory rfqOrder = _makeTestRfqOrder();
|
||||
rfqOrder.taker = otherSignerAddress;
|
||||
rfqOrder.makerToken = weth;
|
||||
_mintTo(address(weth), rfqOrder.maker, rfqOrder.makerAmount);
|
||||
_mintTo(address(dai), otherSignerAddress, 2e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForEth.selector,
|
||||
dai,
|
||||
_makeArray(
|
||||
_makeRfqSubcall(rfqOrder),
|
||||
_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(weth)), 1e18)
|
||||
),
|
||||
2e18,
|
||||
11e18
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// nested
|
||||
|
||||
function test_metaTransaction_multiplexBatchSellTokenForToken_nestedUniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
address[] memory tokens = _makeArray(address(dai), address(zrx));
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexBatchSellTokenForToken.selector,
|
||||
dai,
|
||||
zrx,
|
||||
_makeArray(
|
||||
_makeNestedMultiHopSellSubcall(tokens, _makeArray(_makeUniswapV3MultiHopSubcall(tokens)), 1e18)
|
||||
),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForToken_nestedUniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
_makeArray(address(dai), address(zrx)),
|
||||
_makeArray(
|
||||
_makeNestedBatchSellSubcall(
|
||||
_makeArray(_makeUniswapV3BatchSubcall(_makeArray(address(dai), address(zrx)), 1e18))
|
||||
)
|
||||
),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// multi hop for eth
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForEth_uniswapV3() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, weth, 10e18, 10e18);
|
||||
address[] memory tokens = _makeArray(address(dai), address(weth));
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForEth.selector,
|
||||
tokens,
|
||||
_makeArray(_makeUniswapV3MultiHopSubcall(tokens)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForEth_uniswapV3_revertsNotWeth() external {
|
||||
_createUniswapV3Pool(uniV3Factory, dai, zrx, 10e18, 10e18);
|
||||
address[] memory tokens = _makeArray(address(dai), address(zrx));
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
IMetaTransactionsFeatureV2.MetaTransactionDataV2 memory mtx;
|
||||
LibSignature.Signature memory sig;
|
||||
(mtx, sig) = _makeMetaTransactionV2(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForEth.selector,
|
||||
tokens,
|
||||
_makeArray(_makeUniswapV3MultiHopSubcall(tokens)),
|
||||
1e18,
|
||||
1
|
||||
)
|
||||
);
|
||||
|
||||
vm.expectRevert("MetaTransactionsFeature::multiplexMultiHopSellTokenForEth/NOT_WETH");
|
||||
zeroExDeployed.zeroEx.executeMetaTransactionV2(mtx, sig);
|
||||
}
|
||||
|
||||
function test_metaTransaction_multiplexMultiHopSellTokenForEth_uniswapV2UniswapV3() external {
|
||||
_createUniswapV2Pool(uniV2Factory, dai, shib, 10e18, 10e18);
|
||||
_createUniswapV3Pool(uniV3Factory, shib, weth, 10e18, 10e18);
|
||||
_mintTo(address(dai), otherSignerAddress, 1e18);
|
||||
|
||||
_executeMetaTransaction(
|
||||
abi.encodeWithSelector(
|
||||
zeroExDeployed.zeroEx.multiplexMultiHopSellTokenForToken.selector,
|
||||
_makeArray(address(dai), address(shib), address(weth)),
|
||||
_makeArray(
|
||||
_makeUniswapV2MultiHopSubcall(_makeArray(address(dai), address(shib)), false),
|
||||
_makeUniswapV3MultiHopSubcall(_makeArray(address(shib), address(weth)))
|
||||
),
|
||||
1e18,
|
||||
10e18
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -4,62 +4,48 @@
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0x952ffc4c47d66b454a8181f5c68b6248e18b66ec",
|
||||
"TraderJoeV2Quoter": "0x0000000000000000000000000000000000000000",
|
||||
"TraderJoeV2Router": "0x0000000000000000000000000000000000000000"
|
||||
"KyberElasticPool": "0x952ffc4c47d66b454a8181f5c68b6248e18b66ec"
|
||||
},
|
||||
"56": {
|
||||
"UniswapV2Router": "0x10ed43c718714eb63d5aa57b78b54704e256024e",
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0xfbfab68ba077d099cd4b66fa76920572cc0b557c",
|
||||
"TraderJoeV2Quoter": "0x0000000000000000000000000000000000000000",
|
||||
"TraderJoeV2Router": "0x0000000000000000000000000000000000000000"
|
||||
"KyberElasticPool": "0xfbfab68ba077d099cd4b66fa76920572cc0b557c"
|
||||
},
|
||||
"137": {
|
||||
"UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506",
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0xf9cc934753a127100585812181ac04d07158a4c2",
|
||||
"TraderJoeV2Quoter": "0x0000000000000000000000000000000000000000",
|
||||
"TraderJoeV2Router": "0x0000000000000000000000000000000000000000"
|
||||
"KyberElasticPool": "0xf9cc934753a127100585812181ac04d07158a4c2"
|
||||
},
|
||||
"43114": {
|
||||
"UniswapV2Router": "0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10",
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0x6038373de7f64da99b2a31951628b7d778b2c3cf",
|
||||
"TraderJoeV2Quoter": "0x64b57F4249aA99a812212cee7DAEFEDC40B203cD",
|
||||
"TraderJoeV2Router": "0xb4315e873dBcf96Ffd0acd8EA43f689D8c20fB30"
|
||||
"KyberElasticPool": "0x6038373de7f64da99b2a31951628b7d778b2c3cf"
|
||||
},
|
||||
"250": {
|
||||
"UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506",
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0x8dcf5fed6ae6bf0befb5e4f0c9414c2cb9a4ed01",
|
||||
"TraderJoeV2Quoter": "0x0000000000000000000000000000000000000000",
|
||||
"TraderJoeV2Router": "0x0000000000000000000000000000000000000000"
|
||||
"KyberElasticPool": "0x8dcf5fed6ae6bf0befb5e4f0c9414c2cb9a4ed01"
|
||||
},
|
||||
"10": {
|
||||
"UniswapV2Router": "0x0000000000000000000000000000000000000000",
|
||||
"UniswapV3Router": "0x61ffe014ba17989e743c5f6cb21bf9697530b21e",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0x7e29ccaa4bf2894aca02c77e6b99cafc1d24b2f5",
|
||||
"TraderJoeV2Quoter": "0x0000000000000000000000000000000000000000",
|
||||
"TraderJoeV2Router": "0x0000000000000000000000000000000000000000"
|
||||
"KyberElasticPool": "0x7e29ccaa4bf2894aca02c77e6b99cafc1d24b2f5"
|
||||
},
|
||||
"42161": {
|
||||
"UniswapV2Router": "0x1b02da8cb0d097eb8d57a175b88c7d8b47997506",
|
||||
"UniswapV3Router": "0x0000000000000000000000000000000000000000",
|
||||
"KyberElasticQuoter": "0x0d125c15d54ca1f8a813c74a81aee34ebb508c1f",
|
||||
"KyberElasticRouter": "0xc1e7dfe73e1598e3910ef4c7845b68a9ab6f4c83",
|
||||
"KyberElasticPool": "0x087abaab9cd85025a8b3916948c69fe173c837ea",
|
||||
"TraderJoeV2Quoter": "0x64b57F4249aA99a812212cee7DAEFEDC40B203cD",
|
||||
"TraderJoeV2Router": "0xb4315e873dBcf96Ffd0acd8EA43f689D8c20fB30"
|
||||
"KyberElasticPool": "0x087abaab9cd85025a8b3916948c69fe173c837ea"
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@
|
||||
"43114": {
|
||||
"WrappedNativeToken": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7",
|
||||
"DAI": "0xd586e7f844cea2f87f50152665bcbc2c279d8d70",
|
||||
"USDC": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
||||
"USDT": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"
|
||||
"USDC": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664",
|
||||
"USDT": "0xc7198437980c041c805A1EDcbA50c1Ce5db95118"
|
||||
},
|
||||
"250": {
|
||||
"WrappedNativeToken": "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83",
|
||||
|
@ -1,219 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../utils/ForkUtils.sol";
|
||||
import "../utils/TestUtils.sol";
|
||||
import "src/IZeroEx.sol";
|
||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
|
||||
import "src/features/TransformERC20Feature.sol";
|
||||
import "src/features/multiplex/MultiplexFeature.sol";
|
||||
import "src/external/TransformerDeployer.sol";
|
||||
import "src/transformers/WethTransformer.sol";
|
||||
import "src/transformers/FillQuoteTransformer.sol";
|
||||
import "src/transformers/bridges/BridgeProtocols.sol";
|
||||
import "src/features/OtcOrdersFeature.sol";
|
||||
|
||||
contract MultiplexRfqtTest is Test, ForkUtils, TestUtils {
|
||||
using LibERC20TokenV06 for IERC20Token;
|
||||
using LibERC20TokenV06 for IEtherToken;
|
||||
|
||||
function setUp() public {
|
||||
_setup();
|
||||
}
|
||||
|
||||
function test_swapEthForUSDTThroughFqtOtcs() public {
|
||||
log_string("SwapEthForUSDTThroughFqtOtc");
|
||||
/* */
|
||||
for (uint256 i = 0; i < 1; i++) {
|
||||
//skip fantom/avax failing test
|
||||
if (i == 3 || i == 4) {
|
||||
continue;
|
||||
}
|
||||
vm.selectFork(forkIds[chains[i]]);
|
||||
log_named_string(" Selecting Fork On", chains[i]);
|
||||
vm.deal(address(this), 1e18);
|
||||
labelAddresses(
|
||||
chains[i],
|
||||
indexChainsByChain[chains[i]],
|
||||
getTokens(i),
|
||||
getContractAddresses(i),
|
||||
getLiquiditySourceAddresses(i)
|
||||
);
|
||||
|
||||
//redeploy and migrate multiplexFeature and OtcOrders for logging
|
||||
|
||||
MultiplexFeature multiplexFeature = new MultiplexFeature(
|
||||
address(IZERO_EX),
|
||||
IEtherToken(tokens.WrappedNativeToken),
|
||||
ILiquidityProviderSandbox(addresses.exchangeProxyLiquidityProviderSandbox),
|
||||
address(0), // uniswapFactory
|
||||
address(0), // sushiswapFactory
|
||||
bytes32(0), // uniswapPairInitCodeHash
|
||||
bytes32(0) // sushiswapPairInitCodeHash
|
||||
);
|
||||
|
||||
OtcOrdersFeature otcOrdersFeature = new OtcOrdersFeature(
|
||||
address(addresses.exchangeProxy),
|
||||
tokens.WrappedNativeToken
|
||||
);
|
||||
|
||||
vm.label(address(multiplexFeature), "zeroEx/NewMultiplexFeature");
|
||||
vm.label(address(otcOrdersFeature), "zeroEx/NewOtcOrdersFeature");
|
||||
vm.prank(IZeroEx(addresses.exchangeProxy).owner());
|
||||
|
||||
IZeroEx(addresses.exchangeProxy).migrate(
|
||||
address(otcOrdersFeature),
|
||||
abi.encodeWithSelector(OtcOrdersFeature.migrate.selector),
|
||||
address(addresses.exchangeProxy)
|
||||
);
|
||||
vm.prank(IZeroEx(addresses.exchangeProxy).owner());
|
||||
IZeroEx(addresses.exchangeProxy).migrate(
|
||||
address(multiplexFeature),
|
||||
abi.encodeWithSelector(MultiplexFeature.migrate.selector),
|
||||
address(addresses.exchangeProxy)
|
||||
);
|
||||
swapMultihopOtc(getTokens(i), getContractAddresses(i), getLiquiditySourceAddresses(i));
|
||||
}
|
||||
}
|
||||
|
||||
/* solhint-disable function-max-lines */
|
||||
|
||||
function swapMultihopOtc(
|
||||
TokenAddresses memory tokens,
|
||||
ContractAddresses memory addresses,
|
||||
LiquiditySources memory sources
|
||||
) public onlyForked {
|
||||
IZERO_EX = IZeroEx(addresses.exchangeProxy);
|
||||
|
||||
address[] memory tradeTokens = new address[](3);
|
||||
tradeTokens[0] = address(tokens.WrappedNativeToken);
|
||||
tradeTokens[1] = address(tokens.USDC);
|
||||
tradeTokens[2] = address(tokens.DAI);
|
||||
|
||||
deal(tradeTokens[0], address(this), 1e18);
|
||||
|
||||
tokens.WrappedNativeToken.approveIfBelow(addresses.exchangeProxy, uint(-1));
|
||||
uint inputAmount = 1e18;
|
||||
uint outputAmount = 5e17;
|
||||
|
||||
IMultiplexFeature.MultiHopSellSubcall[] memory subcalls = new IMultiplexFeature.MultiHopSellSubcall[](2);
|
||||
|
||||
IMultiplexFeature.MultiHopSellSubcall memory subcall1;
|
||||
subcall1.id = IMultiplexFeature.MultiplexSubcall.OTC;
|
||||
|
||||
//subcall.data = abi.encode(address[], LibNativeOrder.OtcOrder, LibSignature.Signature);
|
||||
(LibNativeOrder.OtcOrder memory order1, LibSignature.Signature memory signature1) = createOtcOrder(
|
||||
tokens.WrappedNativeToken,
|
||||
tokens.USDC,
|
||||
1e18,
|
||||
5e17,
|
||||
0
|
||||
);
|
||||
subcall1.data = abi.encode(order1, signature1);
|
||||
|
||||
IMultiplexFeature.MultiHopSellSubcall memory subcall2;
|
||||
subcall2.id = IMultiplexFeature.MultiplexSubcall.OTC;
|
||||
(LibNativeOrder.OtcOrder memory order2, LibSignature.Signature memory signature2) = createOtcOrder(
|
||||
tokens.USDC,
|
||||
tokens.DAI,
|
||||
5e17,
|
||||
5e17,
|
||||
1
|
||||
);
|
||||
subcall2.data = abi.encode(order2, signature2);
|
||||
|
||||
subcalls[0] = subcall1;
|
||||
subcalls[1] = subcall2;
|
||||
|
||||
uint balanceBefore = tokens.DAI.balanceOf(address(this));
|
||||
emit log_named_uint("DAI Balance Before", balanceBefore);
|
||||
emit log_string("Multihop Rfqt: WETH->USDC->DAI");
|
||||
|
||||
/// @dev Sells `sellAmount` of the input token (`tokens[0]`)
|
||||
/// via the given sequence of tokens and calls.
|
||||
/// The last token in `tokens` is the output token that
|
||||
/// will ultimately be sent to `msg.sender`
|
||||
/// @param tokens The sequence of tokens to use for the sell,
|
||||
/// i.e. `tokens[i]` will be sold for `tokens[i+1]` via
|
||||
/// `calls[i]`.
|
||||
/// @param calls The sequence of calls to use for the sell.
|
||||
/// @param sellAmount The amount of `inputToken` to sell.
|
||||
/// @param minBuyAmount The minimum amount of output tokens that
|
||||
/// must be bought for this function to not revert.
|
||||
/// @return boughtAmount The amount of output tokens bought.
|
||||
IZERO_EX.multiplexMultiHopSellTokenForToken(
|
||||
// input token[] [input, intermediate, output]
|
||||
tradeTokens,
|
||||
//array of subcalls [{},{}]
|
||||
subcalls,
|
||||
// input token amount
|
||||
inputAmount,
|
||||
// min output token amount
|
||||
outputAmount
|
||||
);
|
||||
uint balanceAfter = tokens.DAI.balanceOf(address(this));
|
||||
emit log_named_uint("DAI Balance After", balanceAfter - balanceBefore);
|
||||
require(balanceAfter >= 5e17, "Failed: UNDERBOUGHT");
|
||||
}
|
||||
|
||||
function createOtcOrder(
|
||||
IERC20Token inputToken,
|
||||
IERC20Token ouputToken,
|
||||
uint128 takerAmount,
|
||||
uint128 makerAmount,
|
||||
uint bump
|
||||
) public returns (LibNativeOrder.OtcOrder memory order, LibSignature.Signature memory signature) {
|
||||
LibNativeOrder.OtcOrder memory order;
|
||||
LibSignature.Signature memory signature;
|
||||
order.makerToken = ouputToken;
|
||||
order.takerToken = inputToken;
|
||||
order.takerAmount = takerAmount;
|
||||
order.makerAmount = makerAmount;
|
||||
uint privateKey;
|
||||
|
||||
(order.maker, privateKey) = _getSigner();
|
||||
|
||||
deal(address(order.makerToken), order.maker, 2e20);
|
||||
deal(address(order.takerToken), order.maker, 2e20);
|
||||
|
||||
vm.startPrank(order.maker);
|
||||
IERC20Token(order.makerToken).approveIfBelow(addresses.exchangeProxy, 2e20);
|
||||
|
||||
order.taker = address(0);
|
||||
order.txOrigin = address(tx.origin);
|
||||
order.expiryAndNonce = encodeExpiryAndNonce(order.maker, bump);
|
||||
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, IZERO_EX.getOtcOrderHash(order));
|
||||
|
||||
vm.stopPrank();
|
||||
signature.signatureType = LibSignature.SignatureType.EIP712;
|
||||
signature.v = v;
|
||||
signature.r = r;
|
||||
signature.s = s;
|
||||
|
||||
return (order, signature);
|
||||
}
|
||||
|
||||
/* solhint-enable function-max-lines */
|
||||
function encodeExpiryAndNonce(address maker, uint bump) public returns (uint256) {
|
||||
uint256 expiry = (block.timestamp + 120) << 192;
|
||||
uint256 bucket = (0 + bump) << 128;
|
||||
uint256 nonce = vm.getNonce(maker);
|
||||
return expiry | bucket | nonce;
|
||||
}
|
||||
}
|
@ -54,76 +54,6 @@ contract SwapERC20ForERC20Test is Test, ForkUtils, TestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
function test_swapERC20ForERC20OnTraderJoeV2() public {
|
||||
for (uint256 i = 0; i < chains.length; i++) {
|
||||
// TraderJoeV2 mixin only enabled on Avalanche and Arbitrum
|
||||
if (i != 3 && i != 6) {
|
||||
continue;
|
||||
}
|
||||
vm.selectFork(forkIds[chains[i]]);
|
||||
labelAddresses(
|
||||
chains[i],
|
||||
indexChainsByChain[chains[i]],
|
||||
getTokens(i),
|
||||
getContractAddresses(i),
|
||||
getLiquiditySourceAddresses(i)
|
||||
);
|
||||
swapOnTraderJoeV2(getTokens(i), getContractAddresses(i), getLiquiditySourceAddresses(i));
|
||||
}
|
||||
}
|
||||
|
||||
function swapOnTraderJoeV2(
|
||||
TokenAddresses memory tokens,
|
||||
ContractAddresses memory addresses,
|
||||
LiquiditySources memory sources
|
||||
) public onlyForked {
|
||||
if (sources.TraderJoeV2Router == address(0)) {
|
||||
emit log_string("TraderJoeV2Router not available on this chain");
|
||||
return;
|
||||
}
|
||||
if (sources.TraderJoeV2Quoter == address(0)) {
|
||||
emit log_string("TraderJoeV2Quoter not available on this chain");
|
||||
return;
|
||||
}
|
||||
|
||||
FillQuoteTransformer.TransformData memory fqtData;
|
||||
fqtData.side = FillQuoteTransformer.Side.Sell;
|
||||
fqtData.sellToken = IERC20Token(address(tokens.USDC));
|
||||
fqtData.buyToken = IERC20Token(address(tokens.USDT));
|
||||
fqtData.fillSequence = new FillQuoteTransformer.OrderType[](1);
|
||||
fqtData.fillSequence[0] = FillQuoteTransformer.OrderType.Bridge;
|
||||
fqtData.fillAmount = 1e6;
|
||||
|
||||
(uint256 amountOut, uint256 binStep, uint256 version) = sampleTraderJoeV2(
|
||||
fqtData.fillAmount,
|
||||
address(fqtData.sellToken),
|
||||
address(fqtData.buyToken),
|
||||
sources.TraderJoeV2Quoter
|
||||
);
|
||||
log_named_uint("amountOut", amountOut);
|
||||
|
||||
IBridgeAdapter.BridgeOrder memory order;
|
||||
{
|
||||
address[] memory tokenPath = new address[](2);
|
||||
tokenPath[0] = address(fqtData.sellToken);
|
||||
tokenPath[1] = address(fqtData.buyToken);
|
||||
uint256[] memory binSteps = new uint256[](1);
|
||||
binSteps[0] = binStep;
|
||||
uint256[] memory versions = new uint256[](1);
|
||||
versions[0] = version;
|
||||
order.bridgeData = abi.encode(address(sources.TraderJoeV2Router), tokenPath, binSteps, versions);
|
||||
}
|
||||
|
||||
order.source = bytes32(uint256(BridgeProtocols.TRADERJOEV2) << 128);
|
||||
order.takerTokenAmount = fqtData.fillAmount;
|
||||
order.makerTokenAmount = amountOut;
|
||||
|
||||
fqtData.bridgeOrders = new IBridgeAdapter.BridgeOrder[](1);
|
||||
fqtData.bridgeOrders[0] = order;
|
||||
|
||||
settleAndLogBalances(fqtData, tokens, addresses);
|
||||
}
|
||||
|
||||
function swapOnKyberElastic(
|
||||
TokenAddresses memory tokens,
|
||||
ContractAddresses memory addresses,
|
||||
@ -141,6 +71,20 @@ contract SwapERC20ForERC20Test is Test, ForkUtils, TestUtils {
|
||||
emit log_string("KyberElasticPool not available on this chain");
|
||||
return;
|
||||
}
|
||||
ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](2);
|
||||
|
||||
transformations[0].deploymentNonce = _findTransformerNonce(
|
||||
address(addresses.transformers.wethTransformer),
|
||||
address(addresses.exchangeProxyTransformerDeployer)
|
||||
);
|
||||
emit log_named_uint("WethTransformer nonce", transformations[0].deploymentNonce);
|
||||
createNewFQT(tokens.WrappedNativeToken, addresses.exchangeProxy, addresses.exchangeProxyTransformerDeployer);
|
||||
transformations[0].data = abi.encode(LibERC20Transformer.ETH_TOKEN_ADDRESS, 1e18);
|
||||
transformations[1].deploymentNonce = _findTransformerNonce(
|
||||
address(fillQuoteTransformer),
|
||||
address(addresses.exchangeProxyTransformerDeployer)
|
||||
);
|
||||
emit log_named_uint("FillQuoteTransformer nonce", transformations[1].deploymentNonce);
|
||||
|
||||
FillQuoteTransformer.TransformData memory fqtData;
|
||||
fqtData.side = FillQuoteTransformer.Side.Sell;
|
||||
@ -167,8 +111,37 @@ contract SwapERC20ForERC20Test is Test, ForkUtils, TestUtils {
|
||||
order.makerTokenAmount = amountOut;
|
||||
order.bridgeData = abi.encode(address(sources.KyberElasticRouter), path);
|
||||
fqtData.bridgeOrders[0] = order;
|
||||
transformations[1].data = abi.encode(fqtData);
|
||||
|
||||
settleAndLogBalances(fqtData, tokens, addresses);
|
||||
vm.deal(address(this), 1e18);
|
||||
uint256 balanceETHBefore = address(this).balance;
|
||||
uint256 balanceERC20Before = IERC20Token(tokens.USDT).balanceOf(address(this));
|
||||
|
||||
writeTokenBalance(address(this), address(tokens.USDC), 1e16);
|
||||
uint256 balanceUSDCbefore = IERC20Token(tokens.USDC).balanceOf(address(this));
|
||||
|
||||
IERC20Token(address(tokens.USDC)).approve(addresses.exchangeProxy, 1e16);
|
||||
|
||||
IZeroEx(payable(addresses.exchangeProxy)).transformERC20{value: 1e18}(
|
||||
// input token
|
||||
IERC20Token(address(tokens.USDC)),
|
||||
// output token
|
||||
IERC20Token(address(tokens.USDT)),
|
||||
// input token amount
|
||||
1e6,
|
||||
// min output token amount
|
||||
order.makerTokenAmount,
|
||||
// list of transform
|
||||
transformations
|
||||
);
|
||||
|
||||
log_named_uint("NativeAsset balance before", balanceETHBefore);
|
||||
log_named_uint("ERC-20 balance before", balanceERC20Before);
|
||||
log_named_uint("NativeAsset balance after", balanceETHBefore - address(this).balance);
|
||||
log_named_uint("ERC-20 balance after", IERC20Token(tokens.USDT).balanceOf(address(this)) - balanceERC20Before);
|
||||
log_named_uint("USDC balance before", balanceUSDCbefore);
|
||||
log_named_uint("USDC balance after", IERC20Token(tokens.USDT).balanceOf(address(tokens.USDC)));
|
||||
assert(IERC20Token(tokens.USDT).balanceOf(address(this)) > 0);
|
||||
}
|
||||
|
||||
function sampleKyberElastic(
|
||||
@ -177,7 +150,7 @@ contract SwapERC20ForERC20Test is Test, ForkUtils, TestUtils {
|
||||
address makerToken,
|
||||
address quoter,
|
||||
address pool
|
||||
) private returns (uint256 makerTokenAmount, bytes memory path) {
|
||||
) public returns (uint256 makerTokenAmount, bytes memory path) {
|
||||
log_string(" Sampling KyberElastic for tokens");
|
||||
log_named_address(" ", takerToken);
|
||||
log_string(" -> ");
|
||||
@ -194,67 +167,4 @@ contract SwapERC20ForERC20Test is Test, ForkUtils, TestUtils {
|
||||
(uint256 amountOut, , , ) = kyberQuoter.quoteExactInput(path, amount);
|
||||
return (amountOut, path);
|
||||
}
|
||||
|
||||
function sampleTraderJoeV2(
|
||||
uint256 amount,
|
||||
address takerToken,
|
||||
address makerToken,
|
||||
address quoter
|
||||
) private returns (uint256 makerTokenAmount, uint256 binStep, uint256 version) {
|
||||
log_string("Sampling TraderJoeV2");
|
||||
log_named_address("takerToken", takerToken);
|
||||
log_named_address("makerToken", makerToken);
|
||||
log_named_address("quoter", quoter);
|
||||
|
||||
address[] memory tokenPath = new address[](2);
|
||||
tokenPath[0] = takerToken;
|
||||
tokenPath[1] = makerToken;
|
||||
|
||||
ITraderJoeV2Quoter.Quote memory quote = ITraderJoeV2Quoter(quoter).findBestPathFromAmountIn(
|
||||
tokenPath,
|
||||
uint128(amount)
|
||||
);
|
||||
|
||||
return (quote.amounts[1], quote.binSteps[0], uint256(quote.versions[0]));
|
||||
}
|
||||
|
||||
function deployFQTAndGetDeploymentNonce(
|
||||
TokenAddresses memory tokens,
|
||||
ContractAddresses memory addresses
|
||||
) private returns (uint32) {
|
||||
createNewFQT(tokens.WrappedNativeToken, addresses.exchangeProxy, addresses.exchangeProxyTransformerDeployer);
|
||||
return
|
||||
_findTransformerNonce(address(fillQuoteTransformer), address(addresses.exchangeProxyTransformerDeployer));
|
||||
}
|
||||
|
||||
function settleAndLogBalances(
|
||||
FillQuoteTransformer.TransformData memory fqtData,
|
||||
TokenAddresses memory tokens,
|
||||
ContractAddresses memory addresses
|
||||
) private {
|
||||
ITransformERC20Feature.Transformation[] memory transformations = new ITransformERC20Feature.Transformation[](1);
|
||||
transformations[0].deploymentNonce = deployFQTAndGetDeploymentNonce(tokens, addresses);
|
||||
transformations[0].data = abi.encode(fqtData);
|
||||
|
||||
address sellToken = address(fqtData.sellToken);
|
||||
address buyToken = address(fqtData.buyToken);
|
||||
|
||||
writeTokenBalance(address(this), sellToken, 1e16);
|
||||
uint256 sellTokenBalanceBefore = IERC20Token(sellToken).balanceOf(address(this));
|
||||
uint256 buyTokenBalanceBefore = IERC20Token(buyToken).balanceOf(address(this));
|
||||
|
||||
IERC20Token(sellToken).approve(addresses.exchangeProxy, 1e16);
|
||||
IZeroEx(payable(addresses.exchangeProxy)).transformERC20(
|
||||
IERC20Token(sellToken),
|
||||
IERC20Token(buyToken),
|
||||
fqtData.fillAmount,
|
||||
fqtData.bridgeOrders[0].makerTokenAmount,
|
||||
transformations
|
||||
);
|
||||
|
||||
log_named_uint("sellToken balance before", sellTokenBalanceBefore);
|
||||
log_named_uint("sellToken balance after", IERC20Token(sellToken).balanceOf(address(this)));
|
||||
log_named_uint("buyToken balance before", buyTokenBalanceBefore);
|
||||
log_named_uint("buyToken balance after", IERC20Token(buyToken).balanceOf(address(this)));
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../../contracts/src/transformers/bridges/AvalancheBridgeAdapter.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BridgeProtocols.sol";
|
||||
|
||||
contract AvalancheBridgeAdapterTest is Test {
|
||||
address constant WAVAX = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;
|
||||
|
||||
AvalancheBridgeAdapter private adapter;
|
||||
|
||||
function setUp() public {
|
||||
vm.chainId(43114);
|
||||
adapter = new AvalancheBridgeAdapter(IEtherToken(WAVAX));
|
||||
}
|
||||
|
||||
function testSupportsUniswapV3() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.UNISWAPV3) << 128)));
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BSCBridgeAdapter.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BridgeProtocols.sol";
|
||||
|
||||
contract BSCBridgeAdapterTest is Test {
|
||||
address constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
|
||||
|
||||
BSCBridgeAdapter private adapter;
|
||||
|
||||
function setUp() public {
|
||||
vm.chainId(56);
|
||||
adapter = new BSCBridgeAdapter(IEtherToken(WBNB));
|
||||
}
|
||||
|
||||
function testSupportsUniswapV3() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.UNISWAPV3) << 128)));
|
||||
}
|
||||
|
||||
function testSupportMaverickV1() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.MAVERICKV1) << 128)));
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BaseBridgeAdapter.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BridgeProtocols.sol";
|
||||
|
||||
contract BaseBridgeAdapterTest is Test {
|
||||
address constant WETH = 0x4200000000000000000000000000000000000006;
|
||||
|
||||
BaseBridgeAdapter private adapter;
|
||||
|
||||
function setUp() public {
|
||||
vm.chainId(8453);
|
||||
adapter = new BaseBridgeAdapter(IEtherToken(WETH));
|
||||
}
|
||||
|
||||
function testSupportsUniswapV3() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.UNISWAPV3) << 128)));
|
||||
}
|
||||
|
||||
function testSupportMaverickV1() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.MAVERICKV1) << 128)));
|
||||
}
|
||||
|
||||
function testSupportSolidly() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.SOLIDLY) << 128)));
|
||||
}
|
||||
|
||||
function testSupportVelodromeV2() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.VELODROMEV2) << 128)));
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../../contracts/src/transformers/bridges/EthereumBridgeAdapter.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BridgeProtocols.sol";
|
||||
|
||||
contract EthereumBridgeAdapterTest is Test {
|
||||
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
||||
|
||||
EthereumBridgeAdapter private adapter;
|
||||
|
||||
function setUp() public {
|
||||
vm.chainId(1);
|
||||
adapter = new EthereumBridgeAdapter(IEtherToken(WETH));
|
||||
}
|
||||
|
||||
function testSupportsUniswapV3() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.UNISWAPV3) << 128)));
|
||||
}
|
||||
|
||||
function testSupportMaverickV1() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.MAVERICKV1) << 128)));
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2023 ZeroEx Intl.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
pragma solidity ^0.6.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../../contracts/src/transformers/bridges/OptimismBridgeAdapter.sol";
|
||||
import "../../../contracts/src/transformers/bridges/BridgeProtocols.sol";
|
||||
|
||||
contract OptimismBridgeAdapterTest is Test {
|
||||
address constant WETH = 0x4200000000000000000000000000000000000006;
|
||||
|
||||
OptimismBridgeAdapter private adapter;
|
||||
|
||||
function setUp() public {
|
||||
vm.chainId(10);
|
||||
adapter = new OptimismBridgeAdapter(IEtherToken(WETH));
|
||||
}
|
||||
|
||||
function testSupportVelodromeV2() public {
|
||||
assertTrue(adapter.isSupportedSource(bytes32(uint256(BridgeProtocols.VELODROMEV2) << 128)));
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@ import "src/features/FundRecoveryFeature.sol";
|
||||
import "src/features/TransformERC20Feature.sol";
|
||||
import "src/features/OtcOrdersFeature.sol";
|
||||
import "src/features/MetaTransactionsFeature.sol";
|
||||
import "src/features/MetaTransactionsFeatureV2.sol";
|
||||
import "src/features/nft_orders/ERC1155OrdersFeature.sol";
|
||||
import "src/features/nft_orders/ERC721OrdersFeature.sol";
|
||||
import "src/features/UniswapFeature.sol";
|
||||
@ -69,7 +68,6 @@ contract DeployZeroEx is Test {
|
||||
FundRecoveryFeature fundRecoveryFeature;
|
||||
TransformERC20Feature transformERC20Feature;
|
||||
MetaTransactionsFeature metaTransactionsFeature;
|
||||
MetaTransactionsFeatureV2 metaTransactionsFeatureV2;
|
||||
ERC1155OrdersFeature erc1155OrdersFeature;
|
||||
ERC721OrdersFeature erc721OrdersFeature;
|
||||
MultiplexFeature multiplexFeature;
|
||||
@ -135,10 +133,6 @@ contract DeployZeroEx is Test {
|
||||
emit log_named_address("UniswapV3Feature", address(ZERO_EX_DEPLOYED.features.uniswapV3Feature));
|
||||
emit log_named_address("FundRecoveryFeature", address(ZERO_EX_DEPLOYED.features.fundRecoveryFeature));
|
||||
emit log_named_address("MetaTransactionsFeature", address(ZERO_EX_DEPLOYED.features.metaTransactionsFeature));
|
||||
emit log_named_address(
|
||||
"MetaTransactionsFeatureV2",
|
||||
address(ZERO_EX_DEPLOYED.features.metaTransactionsFeatureV2)
|
||||
);
|
||||
emit log_named_address("ERC1155OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature));
|
||||
emit log_named_address("ERC721OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc721OrdersFeature));
|
||||
emit log_named_address("TransformERC20Feature", address(ZERO_EX_DEPLOYED.features.transformERC20Feature));
|
||||
@ -207,10 +201,6 @@ contract DeployZeroEx is Test {
|
||||
);
|
||||
ZERO_EX_DEPLOYED.features.fundRecoveryFeature = new FundRecoveryFeature();
|
||||
ZERO_EX_DEPLOYED.features.metaTransactionsFeature = new MetaTransactionsFeature(address(ZERO_EX));
|
||||
ZERO_EX_DEPLOYED.features.metaTransactionsFeatureV2 = new MetaTransactionsFeatureV2(
|
||||
address(ZERO_EX),
|
||||
ZERO_EX_DEPLOYED.weth
|
||||
);
|
||||
ZERO_EX_DEPLOYED.features.erc1155OrdersFeature = new ERC1155OrdersFeature(
|
||||
address(ZERO_EX),
|
||||
ZERO_EX_DEPLOYED.weth
|
||||
@ -280,11 +270,6 @@ contract DeployZeroEx is Test {
|
||||
abi.encodeWithSelector(MetaTransactionsFeature.migrate.selector),
|
||||
address(this)
|
||||
);
|
||||
IZERO_EX.migrate(
|
||||
address(ZERO_EX_DEPLOYED.features.metaTransactionsFeatureV2),
|
||||
abi.encodeWithSelector(MetaTransactionsFeatureV2.migrate.selector),
|
||||
address(this)
|
||||
);
|
||||
IZERO_EX.migrate(
|
||||
address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature),
|
||||
abi.encodeWithSelector(ERC1155OrdersFeature.migrate.selector),
|
||||
|
@ -88,13 +88,10 @@ struct TokenAddresses {
|
||||
IEtherToken WrappedNativeToken;
|
||||
}
|
||||
|
||||
// keep the names of the struct members in alphabetical order for correct json unparsing
|
||||
struct LiquiditySources {
|
||||
address KyberElasticPool;
|
||||
address KyberElasticQuoter;
|
||||
address KyberElasticRouter;
|
||||
address TraderJoeV2Quoter;
|
||||
address TraderJoeV2Router;
|
||||
address UniswapV2Router;
|
||||
address UniswapV3Router;
|
||||
}
|
||||
@ -103,29 +100,6 @@ interface IFQT {
|
||||
function bridgeAdapter() external returns (address);
|
||||
}
|
||||
|
||||
interface ITraderJoeV2Quoter {
|
||||
enum Version {
|
||||
V1,
|
||||
V2,
|
||||
V2_1
|
||||
}
|
||||
|
||||
struct Quote {
|
||||
address[] route;
|
||||
address[] pairs;
|
||||
uint256[] binSteps;
|
||||
Version[] versions;
|
||||
uint128[] amounts;
|
||||
uint128[] virtualAmountsWithoutSlippage;
|
||||
uint128[] fees;
|
||||
}
|
||||
|
||||
function findBestPathFromAmountIn(
|
||||
address[] calldata route,
|
||||
uint128 amountIn
|
||||
) external view returns (Quote memory quote);
|
||||
}
|
||||
|
||||
interface IKyberElasticQuoter {
|
||||
function quoteExactInput(
|
||||
bytes memory path,
|
||||
|
@ -54,9 +54,6 @@ contract LocalTest is Test, TestUtils {
|
||||
address internal signerAddress;
|
||||
uint256 internal signerKey;
|
||||
|
||||
address internal otherSignerAddress;
|
||||
uint256 internal otherSignerKey;
|
||||
|
||||
function _infiniteApprovals() private {
|
||||
shib.approve(address(zeroExDeployed.zeroEx), type(uint256).max);
|
||||
dai.approve(address(zeroExDeployed.zeroEx), type(uint256).max);
|
||||
@ -95,23 +92,12 @@ contract LocalTest is Test, TestUtils {
|
||||
zrx = IERC20Token(address(new TestMintableERC20Token()));
|
||||
weth = zeroExDeployed.weth;
|
||||
|
||||
// TODO this should be somewhere else
|
||||
string memory mnemonic = "conduct into noodle wreck before satisfy alarm vendor dose lunch vapor party";
|
||||
otherSignerKey = vm.deriveKey(mnemonic, 0);
|
||||
otherSignerAddress = vm.addr(otherSignerKey);
|
||||
vm.label(otherSignerAddress, "zeroEx/OtherGuy");
|
||||
|
||||
_infiniteApprovals();
|
||||
|
||||
vm.startPrank(signerAddress);
|
||||
_infiniteApprovals();
|
||||
vm.stopPrank();
|
||||
|
||||
vm.startPrank(otherSignerAddress);
|
||||
_infiniteApprovals();
|
||||
vm.stopPrank();
|
||||
|
||||
vm.deal(address(this), 20e18);
|
||||
vm.deal(address(this), 10e18);
|
||||
}
|
||||
|
||||
function _mintTo(address token, address recipient, uint256 amount) internal {
|
||||
|
@ -20,8 +20,6 @@ import "forge-std/Test.sol";
|
||||
import "src/transformers/LibERC20Transformer.sol";
|
||||
|
||||
contract TestUtils is Test {
|
||||
address private constant ZERO_ADDRESS = 0x0000000000000000000000000000000000000000;
|
||||
|
||||
function _findTransformerNonce(address transformer, address deployer) internal pure returns (uint32) {
|
||||
address current;
|
||||
for (uint32 i = 0; i < 1024; i++) {
|
||||
|
@ -6,8 +6,6 @@
|
||||
"generated-artifacts/AffiliateFeeTransformer.json",
|
||||
"generated-artifacts/AvalancheBridgeAdapter.json",
|
||||
"generated-artifacts/BSCBridgeAdapter.json",
|
||||
"generated-artifacts/BaseBridgeAdapter.json",
|
||||
"generated-artifacts/BaseGoerliBridgeAdapter.json",
|
||||
"generated-artifacts/BatchFillNativeOrdersFeature.json",
|
||||
"generated-artifacts/CeloBridgeAdapter.json",
|
||||
"generated-artifacts/CurveLiquidityProvider.json",
|
||||
@ -32,7 +30,6 @@
|
||||
"generated-artifacts/LiquidityProviderFeature.json",
|
||||
"generated-artifacts/LogMetadataTransformer.json",
|
||||
"generated-artifacts/MetaTransactionsFeature.json",
|
||||
"generated-artifacts/MetaTransactionsFeatureV2.json",
|
||||
"generated-artifacts/MultiplexFeature.json",
|
||||
"generated-artifacts/NativeOrdersFeature.json",
|
||||
"generated-artifacts/OptimismBridgeAdapter.json",
|
||||
@ -50,8 +47,6 @@
|
||||
"test/generated-artifacts/ArbitrumBridgeAdapter.json",
|
||||
"test/generated-artifacts/AvalancheBridgeAdapter.json",
|
||||
"test/generated-artifacts/BSCBridgeAdapter.json",
|
||||
"test/generated-artifacts/BaseBridgeAdapter.json",
|
||||
"test/generated-artifacts/BaseGoerliBridgeAdapter.json",
|
||||
"test/generated-artifacts/BatchFillNativeOrdersFeature.json",
|
||||
"test/generated-artifacts/BootstrapFeature.json",
|
||||
"test/generated-artifacts/BridgeProtocols.json",
|
||||
@ -93,7 +88,6 @@
|
||||
"test/generated-artifacts/ILiquidityProviderFeature.json",
|
||||
"test/generated-artifacts/ILiquidityProviderSandbox.json",
|
||||
"test/generated-artifacts/IMetaTransactionsFeature.json",
|
||||
"test/generated-artifacts/IMetaTransactionsFeatureV2.json",
|
||||
"test/generated-artifacts/IMooniswapPool.json",
|
||||
"test/generated-artifacts/IMultiplexFeature.json",
|
||||
"test/generated-artifacts/INativeOrdersEvents.json",
|
||||
@ -147,10 +141,10 @@
|
||||
"test/generated-artifacts/LiquidityProviderSandbox.json",
|
||||
"test/generated-artifacts/LogMetadataTransformer.json",
|
||||
"test/generated-artifacts/MetaTransactionsFeature.json",
|
||||
"test/generated-artifacts/MetaTransactionsFeatureV2.json",
|
||||
"test/generated-artifacts/MixinAaveV2.json",
|
||||
"test/generated-artifacts/MixinBalancer.json",
|
||||
"test/generated-artifacts/MixinBalancerV2Batch.json",
|
||||
"test/generated-artifacts/MixinBancor.json",
|
||||
"test/generated-artifacts/MixinBancorV3.json",
|
||||
"test/generated-artifacts/MixinCompound.json",
|
||||
"test/generated-artifacts/MixinCryptoCom.json",
|
||||
@ -161,10 +155,12 @@
|
||||
"test/generated-artifacts/MixinGMX.json",
|
||||
"test/generated-artifacts/MixinKyberDmm.json",
|
||||
"test/generated-artifacts/MixinLido.json",
|
||||
"test/generated-artifacts/MixinMStable.json",
|
||||
"test/generated-artifacts/MixinMakerPSM.json",
|
||||
"test/generated-artifacts/MixinMooniswap.json",
|
||||
"test/generated-artifacts/MixinNerve.json",
|
||||
"test/generated-artifacts/MixinPlatypus.json",
|
||||
"test/generated-artifacts/MixinShell.json",
|
||||
"test/generated-artifacts/MixinSolidly.json",
|
||||
"test/generated-artifacts/MixinSynthetix.json",
|
||||
"test/generated-artifacts/MixinUniswap.json",
|
||||
|
@ -19,7 +19,23 @@
|
||||
"TFillData": true,
|
||||
"IterableIterator": true,
|
||||
"Set": true,
|
||||
"Exclude": true
|
||||
"Exclude": true,
|
||||
"#": "private types below",
|
||||
"SupportedProvider": true,
|
||||
"ContractAddresses": true,
|
||||
"AbiDecoder": true,
|
||||
"TxData": true,
|
||||
"ContractAbi": true,
|
||||
"EncoderOverrides": true,
|
||||
"ContractFunctionObj": true,
|
||||
"ContractTxFunctionObj": true,
|
||||
"ContractArtifact": true,
|
||||
"SimpleContractArtifact": true,
|
||||
"DataItem": true,
|
||||
"BlockRange": true,
|
||||
"IndexedFilterValues": true,
|
||||
"EventCallback": true,
|
||||
"ContractEventArg": true
|
||||
},
|
||||
"ignoredExcessiveTypes": [
|
||||
"NonceSubproviderErrors",
|
||||
|
BIN
docs/_static/img/logo.png
vendored
BIN
docs/_static/img/logo.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
15
docs/_static/img/logo.svg
generated
vendored
Normal file
15
docs/_static/img/logo.svg
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<svg width="1028" height="500" viewBox="0 0 1028 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M656.054 246.637C656.054 163.677 690.359 122.422 743.722 122.422C796.861 122.422 831.839 164.35 831.839 246.637C831.839 328.924 796.861 370.628 743.722 370.628C690.583 370.628 656.054 328.924 656.054 246.637ZM743.498 149.327C704.933 149.327 685.874 185.426 685.874 246.861C685.874 275.785 690.135 298.206 698.206 314.574L773.991 159.641C765.247 152.691 755.157 149.327 743.498 149.327ZM713.677 334.305C722.197 340.807 732.063 344.171 743.722 344.171C782.287 344.171 801.794 307.848 801.794 246.861C801.794 218.61 797.758 196.413 789.462 179.597L713.677 334.305Z" fill="black"/>
|
||||
<path d="M1022.87 194.17L973.991 277.13L1027.35 366.368H994.619L951.794 294.17H939.686L895.964 366.368H864.126L917.713 278.251L869.507 194.17H900.449L939.91 262.556H952.242L992.601 194.17H1022.87Z" fill="black"/>
|
||||
<path d="M105.022 316.009L143.834 275.852L95.583 210.74L34.148 123.812C12.4439 160.852 0 203.969 0 250C0 326.256 34.148 394.529 88.0045 440.381L165.987 385.269C139.462 368.744 118.094 344.686 105.022 316.009Z" fill="black"/>
|
||||
<path d="M183.991 105.022L224.148 143.834L289.26 95.583L376.188 34.148C339.148 12.4439 296.031 0 250 0C173.744 0 105.471 34.148 59.6188 88.0045L114.731 165.987C131.256 139.462 155.314 118.094 183.991 105.022Z" fill="black"/>
|
||||
<path d="M356.166 224.148L404.417 289.26L465.852 376.188C487.556 339.148 500 296.031 500 250C500 173.744 465.852 105.471 411.996 59.6188L334.013 114.731C360.538 131.256 381.906 155.314 394.978 183.991L356.166 224.148Z" fill="black"/>
|
||||
<path d="M440.381 411.996L385.269 334.014C368.744 360.538 344.686 381.906 316.009 394.978L275.852 356.166L210.74 404.417L123.812 465.852C160.852 487.556 203.969 500 250 500C326.256 500 394.529 465.852 440.381 411.996Z" fill="black"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="1027.35" height="500" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
BIN
docs/_static/img/smart_nonce_diagram.webp
vendored
BIN
docs/_static/img/smart_nonce_diagram.webp
vendored
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
@ -4,34 +4,28 @@ Audits
|
||||
|
||||
Below are links to our third-party audit reports.
|
||||
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Release** | **Reports** |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Governance | * `Ourovoros <https://github.com/0xProject/protocol/blob/development/contracts/governance/audits/0xProtocol-06-04-2023-Final.pdf>`__ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| MultiplexFeature | * `ABDK Consulting <https://github.com/0xProject/ZEIPs/blob/master/zeip96_images/ABDK_0x_MetaTransaction_v_1_0.pdf>`__ |
|
||||
| | |
|
||||
| MetaTransactions | |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC721OrdersFeature | * `ABDK Consulting <https://s3.us-east-2.amazonaws.com/zeips.0x.org/audits/abdk-consulting/ABDK_0x_Solidity_v_1_0.pdf>`__ |
|
||||
| | |
|
||||
| | |
|
||||
| ERC1155OrdersFeature | |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V4 | * `Consensys Diligence (December 2020) <https://consensys.net/diligence/audits/2020/12/0x-exchange-v4/>`__ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V3 | * `Trail of Bits <http://zeips.0x.org.s3-website.us-east-2.amazonaws.com/audits/56/trail-of-bits/audit.pdf>`__ |
|
||||
| | * `Consensys Diligence (Exchange) <https://diligence.consensys.net/audits/2019/09/0x-v3-exchange/>`__ |
|
||||
| | * `Consensys Diligence (Staking) <https://diligence.consensys.net/audits/2019/10/0x-v3-staking/>`__ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V2.1 | * `First <https://docs.google.com/document/d/1jYv6V21MfCSwCS5fxD6ZyaLWGzkpRSUO0lZpST94XsA/edit>`_ |
|
||||
| | * `Consensys Diligence <https://github.com/ConsenSys/0x_audit_report_2018-07-23>`_ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| MultiAssetProxy | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2018-12>`__ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC1155Proxy | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2019-05>`__ |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| StaticCallProxy | * No third-party audit. |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC20BridgeProxy | * No third-party audit. |
|
||||
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Release** | **Reports** |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC721OrdersFeature | * `ABDK Consulting <https://s3.us-east-2.amazonaws.com/zeips.0x.org/audits/abdk-consulting/ABDK_0x_Solidity_v_1_0.pdf>`__ |
|
||||
| | |
|
||||
| | |
|
||||
| ERC1155OrdersFeature | |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V4 | * `Consensys Diligence (December 2020) <https://consensys.net/diligence/audits/2020/12/0x-exchange-v4/>`__ |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V3 | * `Trail of Bits <http://zeips.0x.org.s3-website.us-east-2.amazonaws.com/audits/56/trail-of-bits/audit.pdf>`__ |
|
||||
| | * `Consensys Diligence (Exchange) <https://diligence.consensys.net/audits/2019/09/0x-v3-exchange/>`__ |
|
||||
| | * `Consensys Diligence (Staking) <https://diligence.consensys.net/audits/2019/10/0x-v3-staking/>`__ |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V2.1 | * `First <https://docs.google.com/document/d/1jYv6V21MfCSwCS5fxD6ZyaLWGzkpRSUO0lZpST94XsA/edit>`_ |
|
||||
| | * `Consensys Diligence <https://github.com/ConsenSys/0x_audit_report_2018-07-23>`_ |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| MultiAssetProxy | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2018-12>`__ |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC1155Proxy | * `Consensys Diligence <https://github.com/ConsenSys/0x-audit-report-2019-05>`__ |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| StaticCallProxy | * No third-party audit. |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC20BridgeProxy | * No third-party audit. |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------------------------------+
|
||||
|
@ -19,14 +19,14 @@ The following contracts are in scope of the bug bounty. Please note that any bug
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Release** | **Contracts** | **Commit Hash** |
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V4 | * Documentation at `https://docs.0xProtocol.org/en/latest/ <https://docs.0xProtocol.org/en/latest/>`__ | |
|
||||
| | * `ZeroEx.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`__ | |
|
||||
| | * `ZeroExOptimized.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/ZeroExOptimized.sol>`__ | |
|
||||
| | * `external/*.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/external>`__ | |
|
||||
| | * `features/*.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/features>`__ | |
|
||||
| | * `fixins/*.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/fixins>`__ | |
|
||||
| | * `migrations/*.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/migrations>`__ | |
|
||||
| | * `storage/*.sol <https://github.com/0xProject/protocol/tree/development/contracts/zero-ex/contracts/src/storage>`__ | |
|
||||
| Exchange V4 | * Documentation at `https://protocol.0x.org/en/latest/ <https://protocol.0x.org/en/latest/>`__ | `c1177416f5 <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts>`__ |
|
||||
| | * `ZeroEx.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/ZeroEx.sol>`__ | |
|
||||
| | * `ZeroExOptimized.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/ZeroExOptimized.sol>`__ | |
|
||||
| | * `external/*.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/external>`__ | |
|
||||
| | * `features/**.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/features>`__ | |
|
||||
| | * `fixins/*.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/fixins>`__ | |
|
||||
| | * `migrations/*.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/migrations>`__ | |
|
||||
| | * `storage/*.sol <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src/storage>`__ | |
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Exchange V3 | * `ERC20BridgeProxy.sol <https://github.com/0xProject/0x-monorepo/blob/fb8360edfd4f42f2d2b127b95c156eb1b0daa02b/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol>`_ (`spec <https://github.com/0xProject/0x-protocol-specification/blob/master/asset-proxy/erc20-bridge-proxy.md>`__) | `fb8360edfd <https://github.com/0xProject/0x-monorepo/tree/fb8360edfd4f42f2d2b127b95c156eb1b0daa02b/contracts>`__ |
|
||||
| | * `Exchange.sol <https://github.com/0xProject/0x-monorepo/blob/fb8360edfd4f42f2d2b127b95c156eb1b0daa02b/contracts/exchange/contracts/src/Exchange.sol>`__ (`spec <https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md>`__) | |
|
||||
@ -46,6 +46,8 @@ The following contracts are in scope of the bug bounty. Please note that any bug
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ERC20BridgeProxy | * `ERC20BridgeProxy.sol <https://github.com/0xProject/0x-monorepo/blob/281658ba349a2c5088b40b503998bea5020284a6/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol>`__ | `281658ba34 <https://github.com/0xProject/0x-monorepo/tree/281658ba349a2c5088b40b503998bea5020284a6/contracts>`_ |
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ExchangeProxy | * `contracts/src <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src>`__ | `c1177416f5 <https://github.com/0xProject/protocol/tree/c1177416f50c2465ee030dacc14ff996eebd4e74/contracts/zero-ex/contracts/src>`_ |
|
||||
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Bounties
|
||||
--------
|
||||
@ -65,10 +67,19 @@ The final reward amount is at the sole discretion of 0x Labs and will be paid in
|
||||
| Low (CVSS 0.0 - 3.9) | up to $5,000 |
|
||||
+----------------------------+---------------------+
|
||||
|
||||
Recent Inclusions
|
||||
-----------------
|
||||
|
||||
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Change** | **** |
|
||||
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| NFT feature | * Trade ERC721 and ERC1155 assets. See `ZEIP-93 <https://github.com/0xProject/ZEIPs/issues/93>`__ for more details |
|
||||
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
Disclosures
|
||||
-----------
|
||||
Please e-mail all submissions to security@0x.org with the subject "BUG BOUNTY". Your submission
|
||||
should include any steps required to reproduce or exploit the vulnerability. Please allow time for
|
||||
the vulnerability to be fixed before discussing any findings publicly. After receiving a submission,
|
||||
we will contact you with expected timelines for a fix to be implemented.
|
||||
we will contact you with expected timelines for a fix to be implemented.
|
@ -62,16 +62,16 @@ Function timelocks are represented in days, where one day is equivalent to 86,40
|
||||
.. csv-table::
|
||||
:header: "Contract", "Function", "Selector", "Timelock"
|
||||
|
||||
AllowanceTarget, ``addAuthorizedAddress``, ``42f1181e``, 2 day
|
||||
AllowanceTarget, ``addAuthorizedAddress``, ``42f1181e``, 2 days
|
||||
AllowanceTarget, ``removeAuthorizedAddress``, ``70712939``, 0 days
|
||||
AllowanceTarget, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 0 days
|
||||
Governor, ``registerFunctionCall``, ``751ad560``, 2 day
|
||||
ExchangeProxy, ``extend``, ``6eb224cb``, 2 day
|
||||
ExchangeProxy, ``migrate``, ``261fe679``, 2 day
|
||||
Governor, ``registerFunctionCall``, ``751ad560``, 2 days
|
||||
ExchangeProxy, ``extend``, ``6eb224cb``, 2 days
|
||||
ExchangeProxy, ``migrate``, ``261fe679``, 2 days
|
||||
ExchangeProxy, ``rollback``, ``9db64a40``, 0 days
|
||||
ExchangeProxy, ``setQuoteSigner``, ``<deprecation in progress>``, 2 day
|
||||
ExchangeProxy, ``setTransformerDeployer``, ``87c96419``, 2 day
|
||||
ExchangeProxy, ``transferOwnership``, ``f2fde38b``, 2 day
|
||||
ExchangeProxy, ``setQuoteSigner``, ``<deprecation in progress>``, 2 days
|
||||
ExchangeProxy, ``setTransformerDeployer``, ``87c96419``, 2 days
|
||||
ExchangeProxy, ``transferOwnership``, ``f2fde38b``, 2 days
|
||||
StakingProxy, ``addExchangeAddress``, ``8a2e271a``, 14 days
|
||||
StakingProxy, ``removeExchangeAddress``, ``01e28d84``, 14 days
|
||||
StakingProxy, ``attachStakingContract``, ``66615d56``, 14 days
|
||||
|
@ -2,7 +2,7 @@
|
||||
Overview
|
||||
###############################
|
||||
|
||||
The `ZeroEx` (Exchange Proxy) contract implements a delegate-call proxy pattern to create a system of composable smart contracts. This architecture enables 0x Protocol to innovate with minimal friction alongside the growing DeFi ecosystem.
|
||||
The 0x Exchange implements a delegate-call proxy pattern to create a system of composable smart contracts. This architecture enables 0x to innovate with minimal friction alongside the growing DeFi ecosystem.
|
||||
|
||||
The diagram below illustrates our system (click to enlarge).
|
||||
|
||||
@ -24,7 +24,13 @@ The table below defines our smart contract nomenclature.
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Flash Wallet <./flash_wallet.html>`_ | The Flash Wallet is a sandboxed escrow contract that holds funds for Transformers to operate on. For example, the ``WETHtransformer`` wraps any Ether in the Flash Wallet. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Governor <./governor.html>`_ | A smart contract that governs trusted contracts in the system: Proxy, Features, Flash Wallet. |
|
||||
| `Allowance Target <../basics/allowances.html>`_ | Users set their allowances on this contract. It is scheduled to be deprecated after the official V4 release in January, 2021. After which point allowances will be set directly on the Proxy. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Governor <./governor.html>`_ | A MultiSig that governs trusted contracts in the system: Proxy, Features, Flash Wallet. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Transformer Deployer <./transformer_deployer.html>`_ | Deploys Transformers. A transformer is authenticated using a nonce of the Transformer Deployer. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Fee Collectors <./fee_collectors.html>`_ | `Protocol fees <../basics/protocol_fees.html>`_ are paid into these contracts at time-of-fill. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `PLP Sandbox <./plp_sandbox.html>`_ | `PLP <../advanced/plp.html>`_ liquidity providers are called from this sandbox. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
@ -2,22 +2,37 @@
|
||||
Proxy
|
||||
###############################
|
||||
|
||||
The `ZeroEx <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_ contract (also called Exchange Proxy or EP) is the main contract that manages the process and performs the exchange of assets. It implements a per-function proxy pattern where each function can have a distinct implementation contract, also known as "features". The `ZeroEx` contract's sole responsibility is to maintain a mapping of "features" to implementation contracts and route (delegate) calls to per-function implementation contracts through its fallback mechanism.
|
||||
The `ZeroEx <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_ contract implements a per-function proxy pattern. Every function registered to the proxy contract can have a distinct implementation contract. Implementation contracts are called “features” and can expose multiple, related functions. Since features can be upgraded independently, there will no longer be a collective “version” of the API, defaulting to a rolling release model. The ZeroEx contract’s only responsibility is to route (delegate) calls to per-function implementation contracts through its fallback.
|
||||
|
||||
.. image:: ../_static/img/proxy.png
|
||||
:align: center
|
||||
:scale: 100%
|
||||
|
||||
View the code for the Proxy `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_. The deployed contract address for each network can be found in `here <https://github.com/0xProject/protocol/blob/development/packages/contract-addresses/addresses.json>`_.
|
||||
View the code for the Proxy `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_. There is also a `gas-optimized implementation <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroExOptimized.sol>`_ that may be put into production in the future (there is a lot of overhead for our integrators when redeploying this contract).
|
||||
|
||||
Deployment
|
||||
==========
|
||||
At deployment, the ``ZeroEx`` contract goes through an ``InitialMigration`` that bootstraps two core features to the proxy pattern: Function Registry and Ownership.
|
||||
Bootstrapping
|
||||
=============
|
||||
The ZeroEx contract comes pre-loaded with only one Feature: `Bootstrap <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/BootstrapFeature.sol>`_. This exposes a ``bootstrap()`` function that can only be called by the deployer. This function does a few things:
|
||||
|
||||
1. De-register the bootstrap() function, which prevents it being called again.
|
||||
2. Self-destruct.
|
||||
3. Delegatecall the bootstrapper target contract and call data.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Execute a bootstrapper in the context of the proxy.
|
||||
function bootstrap(address target, bytes callData) external
|
||||
|
||||
Below is the bootstrap workflow (click to enlarge).
|
||||
|
||||
.. image:: ../_static/img/bootstrap.png
|
||||
:align: center
|
||||
:scale: 70%
|
||||
|
||||
Function Registry
|
||||
=================
|
||||
|
||||
``SimpleFunctionRegistry`` is one of the initial and core features of the `ZeroEx` contract boostrapped in during the ``InitialMigration``. This feature exposes the following function registry management features: ``extend()`` and ``rollback()``.
|
||||
One of the initial features InitialMigration bootstraps into the ZeroEx contract is the function registry feature, SimpleFunctionRegistry. This feature exposes the following function registry management features: ``extend()`` and ``rollback()``.
|
||||
|
||||
Call ``extend()`` to register a new function (selector) and implementation (address). This also maintains a history of past implementations so we can roll back to one, if needed.
|
||||
|
||||
@ -39,7 +54,7 @@ Call ``rollback()`` to revert a function implementation to a prior version in it
|
||||
|
||||
Ownership
|
||||
=========
|
||||
``Ownable`` is another initial and core feature of the `ZeroEx` contract that is bootstrapped into the proxy during the ``InitialMigration``. This exposes ownership management functions: ``transferOwnership()`` and ``getOwner()``. This feature also enables ubiquitous modifiers such as onlyOwner, so it is an implicit dependency of nearly every other feature.
|
||||
Another Feature, ``InitialMigration``, bootstraps into the proxy is the Ownable feature. This exposes ownership management functions: ``transferOwnership()`` and ``owner()``. This feature also enables ubiquitous modifiers such as onlyOwner, so it is an implicit dependency of nearly every other feature.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
@ -241,24 +256,3 @@ Functions can be re-entered by default; those secured by the ``nonReentrant`` mo
|
||||
**Colliding Function Selectors**
|
||||
|
||||
We manually ensure that function selectors do not collide during PR's. See the `Feature Checklist <./features.html#best-practices>`_ for a complete list of our best practices on Feature Development.
|
||||
|
||||
Initial Bootstrapping
|
||||
=====================
|
||||
|
||||
The way that the initial bootstrapping is accomplished is through the ``bootstrap()`` function that can only be called by the deployer. Check `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/BootstrapFeature.sol>`_ to see the full boostrapping feature.
|
||||
|
||||
This function does a few things:
|
||||
1. De-register the bootstrap() function, which prevents it being called again.
|
||||
2. Self-destruct.
|
||||
3. Delegatecall the bootstrapper target contract and call data.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Execute a bootstrapper in the context of the proxy.
|
||||
function bootstrap(address target, bytes callData) external
|
||||
|
||||
Below is the bootstrap workflow (click to enlarge).
|
||||
|
||||
.. image:: ../_static/img/bootstrap.png
|
||||
:align: center
|
||||
:scale: 70%
|
||||
|
@ -66,8 +66,3 @@ Note: Some addresses have changed across various networks
|
||||
Avalanche, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://snowtrace.io/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
Fantom, `0xdef189deaef76e379df891899eb5a00a94cbc250 <https://ftmscan.com/address/0xdef189deaef76e379df891899eb5a00a94cbc250>`__
|
||||
Celo, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://explorer.celo.org/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
Arbitrum, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://arbiscan.io/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
Base, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://basescan.org/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
zkEVM, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://zkevm.polygonscan.com/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
Sepolia, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://sepolia.etherscan.io/address/0xdef1c0ded9bec7f1a1670819833240f027b25eff>`__
|
||||
Mumbai, `0xf471d32cb40837bf24529fcf17418fc1a4807626 <https://mumbai.polygonscan.com/address/0xf471d32cb40837bf24529fcf17418fc1a4807626>`__
|
||||
|
@ -295,9 +295,9 @@ In both cases, the ``@0x/protocol-utils`` package simplifies generating these si
|
||||
|
||||
The Orderbook
|
||||
=======================
|
||||
Orders can be hosted by any server and are usually represented as a JSON object off-chain. For example, one off-chain way to post and discover orders is through `0x Orderbook API <https://0x.org/docs/category/orderbook-api>`_.
|
||||
Orders are shared through a decentralized and permissionless network, called `0x Mesh <https://0x.org/mesh>`_. The simplest way to post and discover orders is through `0x API <https://0x.org/api>`_. See `this guide <https://0x.org/docs/guides/market-making-on-0x>`_ tailored for Market Makers.
|
||||
|
||||
Below is a table represention and example of how orders should be formatted off-chain.
|
||||
Orders are usually represented as a JSON object off-chain. Below is a table represention and example of how orders should be formatted off-chain.
|
||||
|
||||
JSON representation of RFQ Orders
|
||||
*********************************
|
||||
|
@ -1,75 +0,0 @@
|
||||
Signatures
|
||||
==========
|
||||
|
||||
Signatures are used in several places in 0x Protocol to prove an actor
|
||||
has agreed to the behavior in some off-chain message.
|
||||
|
||||
Signatures are represented by the following struct:
|
||||
|
||||
.. code:: solidity
|
||||
|
||||
struct Signature {
|
||||
// How to validate the signature.
|
||||
SignatureType signatureType;
|
||||
// EC Signature data.
|
||||
uint8 v;
|
||||
// EC Signature data.
|
||||
bytes32 r;
|
||||
// EC Signature data.
|
||||
bytes32 s;
|
||||
}
|
||||
|
||||
Where ``SignatureType`` is:
|
||||
|
||||
.. code:: solidity
|
||||
|
||||
enum SignatureType {
|
||||
ILLEGAL,
|
||||
INVALID,
|
||||
EIP712,
|
||||
ETHSIGN,
|
||||
PRESIGNED
|
||||
}
|
||||
|
||||
Descriptions of the valid signature types follow.
|
||||
|
||||
**EIP712 (``2``)**
|
||||
|
||||
This is the signature type typically used when an order is signed
|
||||
through a UI, such as Metamask. This is commonly achieved by calling
|
||||
some variant of the ``eth_signTypedData`` (which fully utilizes EIP712)
|
||||
JSONRPC command on the Ethereum provider.
|
||||
|
||||
It can also be generated in a headless manner using a standard
|
||||
``ecsign()`` implementation
|
||||
(`example <https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_signature_.md#const-ecsign>`__)
|
||||
by re-hashing the `canonical order
|
||||
hash <signatures.md#limit-order-hashes>`__ with a prefix as follows and
|
||||
signing the result:
|
||||
|
||||
.. code:: solidity
|
||||
|
||||
eip712HashToSign = keccak256(abi.encodePacked(
|
||||
"\x19Ethereum Signed Message:\n32",
|
||||
orderHash
|
||||
));
|
||||
|
||||
ETHSIGN (``3``)
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
This is the signature type typically used when an order is signed in a
|
||||
headless environment (e.g., script or backend). This commonly achieved
|
||||
by calling the ``eth_sign`` JSONRPC command on the Ethereum provider or,
|
||||
perhaps more straight-forwardly, using a standard ``ecsign()``
|
||||
implementation
|
||||
(`example <https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_signature_.md#const-ecsign>`__).
|
||||
Unlike the ``EIP712`` signature type, the hash to sign is simply the
|
||||
`canonical order hash <signatures.md#limit-order-hashes>`__ (no prefix).
|
||||
|
||||
PRESIGNED (``4``)
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
This signature type is used exclusively with NFT orders (721 and 1155)
|
||||
for now. This value indicates that the order maker has previously marked
|
||||
the order as fillable on-chain. The remaining fields in the
|
||||
``Signature`` struct will be ignored.
|
@ -1,466 +0,0 @@
|
||||
###############################
|
||||
NFT Guides - Creating Orders
|
||||
###############################
|
||||
|
||||
The easiest way of creating a 0x NFT order is to use the npm packages `@0x/protocol-utils` and `@0x/utils`
|
||||
|
||||
>>> yarn add @0x/protocol-utils @0x/utils
|
||||
or
|
||||
npm install @0x/protocol-utils @0x/utils
|
||||
|
||||
|
||||
Create an ERC721Order
|
||||
=====================
|
||||
|
||||
The following code snippet shows how to construct a basic ERC721 sell order in JavaScript. In the following example, the seller indicates that they would like to receive ether by providing the sentinel value `0xeee...`` as the `erc20Token`.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
|
||||
// Construct sell order
|
||||
const sellOrder = new ERC721Order({
|
||||
// The EVM blockchain that this order is for, in this case Ethereum mainnet.
|
||||
chainId: 1,
|
||||
// The address of the 0x v4 ExchangeProxy contract on Ethereum.
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
// Whether to sell or buy the given NFT
|
||||
direction: NFTOrder.TradeDirection.SellNFT,
|
||||
// This indicates that the seller would like to receive ETH.
|
||||
erc20Token: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
|
||||
// The price, in this case 1 ETH.
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
// Address of the ERC721 contract.
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
// Token ID of the NFT to sell.
|
||||
erc721TokenId: 123,
|
||||
// Address of the seller. This is also the address that will be
|
||||
// signing this order.
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
// A null taker address allows anyone to fill this order
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
// A unique order nonce
|
||||
nonce: 420,
|
||||
// Order expires in one hour
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
});
|
||||
|
||||
An ERC721 sell order can be created similarly. Note that buy orders must use WETH instead of ether, because the ERC20 `transferFrom` functionality is needed to execute a buy order.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
|
||||
// Construct buy order
|
||||
const buyOrder = new ERC721Order({
|
||||
// The EVM blockchain that this order is for, in this case Ethereum mainnet.
|
||||
chainId: 1,
|
||||
// The address of the 0x v4 ExchangeProxy contract on Ethereum.
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
// Whether to sell or buy the given NFT
|
||||
direction: NFTOrder.TradeDirection.BuyNFT,
|
||||
// Address of the ERC20 token to buy with, in this case WETH.
|
||||
erc20Token: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
||||
// The price, in this case 1 WETH.
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
// Address of the ERC721 contract.
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
// Token ID of the NFT to buy.
|
||||
erc721TokenId: 234,
|
||||
// Address of the buyer. This is also the address that will be
|
||||
// signing this order.
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
// A null taker address allows anyone to fill this order
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
// A unique order nonce
|
||||
nonce: 421,
|
||||
// Order expires in one hour
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
});
|
||||
|
||||
**Choosing a nonce**
|
||||
|
||||
If two orders signed by the same maker have the same nonce, filling or cancelling one can result in the other becoming unfillable.
|
||||
|
||||
::
|
||||
|
||||
Two ERC721 orders with the same nonce cannot both be filled, but two ERC1155 orders with the same nonce can both be filled (as long as the orders are not identical).
|
||||
|
||||
You can use a pseudorandom value or the current timestamp as the order nonce, but nonces can be chosen in a specific way to enable more gas-efficient fills and cancellations. See `Smart Nonces <./smart_nonce.rst>`_ for explanation.
|
||||
|
||||
We recommend using the most significant 128 bits of the nonce as an application/marketplace identifier. The least significant 128 bits of the nonce can be incremented from 0 for each order created by a particular maker.
|
||||
|
||||
**Royalties and Fees**
|
||||
|
||||
0x V4 has flexible support for creator royalties and platform fees. Marketplaces can pay out royalties to creators in real-time, and even have the option to send fees to their own custom fee disbursement contract.
|
||||
Fees are paid by the **buyer**, denominated in the asset paid by the buyer, and are paid **in addition** to the `erc20TokenAmount` specified in the order.
|
||||
The following code snippet shows how to create an ERC721 order with a single fee. Multiple fees can be specified by providing multiple fee objects in the order fees field.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
|
||||
const fee = {
|
||||
// Address to receive the fee. Can be a smart contract.
|
||||
recipient: '0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c',
|
||||
amount: utils.BigNumber('1e17'), // 0.1 ETH
|
||||
// If the fee recipient is a contract, this field can be used
|
||||
// to invoke a callback. In this case, there is no callback.
|
||||
feeData: '0x',
|
||||
};
|
||||
|
||||
// Construct sell order
|
||||
const order = new ERC721Order({
|
||||
chainId: 1,
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
direction: NFTOrder.TradeDirection.SellNFT,
|
||||
erc20Token: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
erc721TokenId: 123,
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
fees: [fee],
|
||||
nonce: 420,
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
});
|
||||
|
||||
**Collection Offers**
|
||||
|
||||
In 0x V4, it is possible to create a bid for any NFT in a particular collection. The following code snippet shows how to create an order to buy any CryptoCoven $WITCH.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
|
||||
const property = {
|
||||
// Providing `address(0)` and `0x` serves as the sentinel
|
||||
// values for a "null property", i.e. any token ID from the
|
||||
// given collection can be used to fill the order.
|
||||
propertyValidator: '0x0000000000000000000000000000000000000000',
|
||||
propertyData: '0x',
|
||||
};
|
||||
|
||||
// Construct sell order
|
||||
const order = new ERC721Order({
|
||||
chainId: 1,
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
direction: NFTOrder.TradeDirection.SellNFT,
|
||||
erc20Token: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
// If one or more properties are specified in the order, the
|
||||
// `erc721TokenId` must be 0.
|
||||
erc721TokenId: 0,
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
erc721TokenProperties: [property],
|
||||
nonce: 420,
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
}
|
||||
|
||||
Sign an ERC721 Order
|
||||
====================
|
||||
|
||||
Off-chain orders must be signed by the order maker to be filled. For on-chain orders, refer to the next section.
|
||||
|
||||
**Signing with a private key**
|
||||
|
||||
Signing an order with a private key is easy: the `ERC721Order` and `ERC1155Order` classes from `@0x/protocol-utils` expose a `getSignatureWithKey` function that take a 0x-prefixed private key string.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder, SignatureType } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
|
||||
// Construct order
|
||||
const order = new ERC721Order({
|
||||
chainId: 1,
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
direction: NFTOrder.TradeDirection.SellNFT,
|
||||
erc20Token: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
erc721TokenId: 123,
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
nonce: 420,
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
});
|
||||
|
||||
// Sign order with private key
|
||||
const signature = await order.getSignatureWithKey(
|
||||
PRIVATE_KEY, // '0x123456789...'
|
||||
SignatureType.EIP712
|
||||
);
|
||||
|
||||
**Signing with ethers**
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const { ERC721Order, NFTOrder, SignatureType } = require("@0x/protocol-utils");
|
||||
const utils = require("@0x/utils");
|
||||
const { ethers } = require("ethers");
|
||||
|
||||
// Construct order
|
||||
const order = new ERC721Order({
|
||||
chainId: 1,
|
||||
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
|
||||
direction: NFTOrder.TradeDirection.SellNFT,
|
||||
erc20Token: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
|
||||
erc20TokenAmount: utils.BigNumber('1e18'),
|
||||
erc721Token: '0x5180db8f5c931aae63c74266b211f580155ecac8',
|
||||
erc721TokenId: 123,
|
||||
maker: '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b',
|
||||
taker: '0x0000000000000000000000000000000000000000',
|
||||
nonce: 420,
|
||||
expiry: new utils.BigNumber(Math.floor(Date.now() / 1000 + 3600)),
|
||||
});
|
||||
|
||||
// Get ethers Signer
|
||||
const provider = new ethers.providers.JsonRpcProvider(/* constructor params */);
|
||||
const signer = provider.getSigner(/* address */);
|
||||
|
||||
const { domain, message } = order.getEIP712TypedData();
|
||||
const types = {
|
||||
[ERC721Order.STRUCT_NAME]: ERC721Order.STRUCT_ABI,
|
||||
['Fee']: NFTOrder.FEE_ABI,
|
||||
['Property']: NFTOrder.PROPERTY_ABI,
|
||||
};
|
||||
const rawSignature = await signer._signTypedData(
|
||||
domain,
|
||||
types,
|
||||
message
|
||||
);
|
||||
const { v, r, s } = ethers.utils.splitSignature(rawSignature);
|
||||
const signature = {
|
||||
v,
|
||||
r,
|
||||
s,
|
||||
signatureType: 2
|
||||
};
|
||||
|
||||
**On-chain Orders**
|
||||
|
||||
Orders can be simultaneously "signed" and listed on-chain using the `preSignERC721Order` or `preSignERC1155Order` functions. Orders can only be signed by the maker address specified in the order.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Approves an ERC721 order on-chain. After pre-signing
|
||||
/// the order, the `PRESIGNED` signature type will become
|
||||
/// valid for that order and signer.
|
||||
/// @param order An ERC721 order.
|
||||
function preSignERC721Order(LibNFTOrder.ERC721Order calldata order)
|
||||
external;
|
||||
|
||||
/// @dev Approves an ERC1155 order on-chain. After pre-signing
|
||||
/// the order, the `PRESIGNED` signature type will become
|
||||
/// valid for that order and signer.
|
||||
/// @param order An ERC1155 order.
|
||||
function preSignERC1155Order(LibNFTOrder.ERC1155Order calldata order)
|
||||
external;
|
||||
|
||||
If an order has been pre-signed, it can be filled by providing a “null” signature with the PRESIGNED signature type (see `LibSignature.sol <https://github.com/0xProject/protocol/blob/refactor/nft-orders/contracts/zero-ex/contracts/src/features/libs/LibSignature.sol#L42-L61>`_):
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
LibSignature.Signature({
|
||||
signatureType: LibSignature.SignatureType.PRESIGNED,
|
||||
v: uint8(0),
|
||||
r: bytes32(0),
|
||||
s: bytes32(0)
|
||||
});
|
||||
|
||||
The pre-sign functions emit the entire order as an event, so that the order is easily indexable by subgraphs and thus easily indexable by subgraphs and thus easily discoverable without the need for an off-chain database.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Emitted when an `ERC721Order` is pre-signed.
|
||||
/// Contains all the fields of the order.
|
||||
event ERC721OrderPreSigned(
|
||||
LibNFTOrder.TradeDirection direction,
|
||||
address maker,
|
||||
address taker,
|
||||
uint256 expiry,
|
||||
uint256 nonce,
|
||||
IERC20TokenV06 erc20Token,
|
||||
uint256 erc20TokenAmount,
|
||||
LibNFTOrder.Fee[] fees,
|
||||
IERC721Token erc721Token,
|
||||
uint256 erc721TokenId,
|
||||
LibNFTOrder.Property[] erc721TokenProperties
|
||||
);
|
||||
|
||||
/// @dev Emitted when an `ERC1155Order` is pre-signed.
|
||||
/// Contains all the fields of the order.
|
||||
event ERC1155OrderPreSigned(
|
||||
LibNFTOrder.TradeDirection direction,
|
||||
address maker,
|
||||
address taker,
|
||||
uint256 expiry,
|
||||
uint256 nonce,
|
||||
IERC20TokenV06 erc20Token,
|
||||
uint256 erc20TokenAmount,
|
||||
LibNFTOrder.Fee[] fees,
|
||||
IERC1155Token erc1155Token,
|
||||
uint256 erc1155TokenId,
|
||||
LibNFTOrder.Property[] erc1155TokenProperties,
|
||||
uint128 erc1155TokenAmount
|
||||
);
|
||||
|
||||
The pre-sign functions also enable smart contracts to create and "sign" NFT orders, opening the door for potential integrations with e.g. multisig wallets.
|
||||
|
||||
Filling an ERC721 Order
|
||||
=======================
|
||||
|
||||
The basic functions used for filling NFT orders are the following:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Sells an ERC721 asset to fill the given order.
|
||||
/// @param buyOrder The ERC721 buy order.
|
||||
/// @param signature The order signature from the maker.
|
||||
/// @param erc721TokenId The ID of the ERC721 asset being
|
||||
/// sold. If the given order specifies properties,
|
||||
/// the asset must satisfy those properties. Otherwise,
|
||||
/// it must equal the tokenId in the order.
|
||||
/// @param unwrapNativeToken If this parameter is true and the
|
||||
/// ERC20 token of the order is e.g. WETH, unwraps the
|
||||
/// token before transferring it to the taker.
|
||||
/// @param callbackData If this parameter is non-zero, invokes
|
||||
/// `zeroExERC721OrderCallback` on `msg.sender` after
|
||||
/// the ERC20 tokens have been transferred to `msg.sender`
|
||||
/// but before transferring the ERC721 asset to the buyer.
|
||||
function sellERC721(
|
||||
LibNFTOrder.ERC721Order calldata buyOrder,
|
||||
LibSignature.Signature calldata signature,
|
||||
uint256 erc721TokenId,
|
||||
bool unwrapNativeToken,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Buys an ERC721 asset by filling the given order.
|
||||
/// @param sellOrder The ERC721 sell order.
|
||||
/// @param signature The order signature.
|
||||
/// @param callbackData If this parameter is non-zero, invokes
|
||||
/// `zeroExERC721OrderCallback` on `msg.sender` after
|
||||
/// the ERC721 asset has been transferred to `msg.sender`
|
||||
/// but before transferring the ERC20 tokens to the seller.
|
||||
/// Native tokens acquired during the callback can be used
|
||||
/// to fill the order.
|
||||
function buyERC721(
|
||||
LibNFTOrder.ERC721Order calldata sellOrder,
|
||||
LibSignature.Signature calldata signature,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external
|
||||
payable;
|
||||
|
||||
/// @dev Sells an ERC1155 asset to fill the given order.
|
||||
/// @param buyOrder The ERC1155 buy order.
|
||||
/// @param signature The order signature from the maker.
|
||||
/// @param erc1155TokenId The ID of the ERC1155 asset being
|
||||
/// sold. If the given order specifies properties,
|
||||
/// the asset must satisfy those properties. Otherwise,
|
||||
/// it must equal the tokenId in the order.
|
||||
/// @param erc1155SellAmount The amount of the ERC1155 asset
|
||||
/// to sell.
|
||||
/// @param unwrapNativeToken If this parameter is true and the
|
||||
/// ERC20 token of the order is e.g. WETH, unwraps the
|
||||
/// token before transferring it to the taker.
|
||||
/// @param callbackData If this parameter is non-zero, invokes
|
||||
/// `zeroExERC1155OrderCallback` on `msg.sender` after
|
||||
/// the ERC20 tokens have been transferred to `msg.sender`
|
||||
/// but before transferring the ERC1155 asset to the buyer.
|
||||
function sellERC1155(
|
||||
LibNFTOrder.ERC1155Order calldata buyOrder,
|
||||
LibSignature.Signature calldata signature,
|
||||
uint256 erc1155TokenId,
|
||||
uint128 erc1155SellAmount,
|
||||
bool unwrapNativeToken,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Buys an ERC1155 asset by filling the given order.
|
||||
/// @param sellOrder The ERC1155 sell order.
|
||||
/// @param signature The order signature.
|
||||
/// @param erc1155BuyAmount The amount of the ERC1155 asset
|
||||
/// to buy.
|
||||
/// @param callbackData If this parameter is non-zero, invokes
|
||||
/// `zeroExERC1155OrderCallback` on `msg.sender` after
|
||||
/// the ERC1155 asset has been transferred to `msg.sender`
|
||||
/// but before transferring the ERC20 tokens to the seller.
|
||||
/// Native tokens acquired during the callback can be used
|
||||
/// to fill the order.
|
||||
function buyERC1155(
|
||||
LibNFTOrder.ERC1155Order calldata sellOrder,
|
||||
LibSignature.Signature calldata signature,
|
||||
uint128 erc1155BuyAmount,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external
|
||||
payable;
|
||||
|
||||
`sellERC721` and `sellERC1155` are used when the caller is **selling** an NFT, so the order being filled is a **buy** order.
|
||||
`buyERC721` and `buyERC1155` are used when the caller is **buying** an NFT, so the order being filled is a **sell** order.
|
||||
Note that the only difference in parameters between the ERC721 and ERC1155 functions is `erc1155BuyAmount`. This value specifies the amount of the ERC1155 asset to sell/buy from the given order, which may be greater than one in the case of semi-fungible ERC1155 assets.
|
||||
|
||||
Cancelling an ERC721 Order
|
||||
==========================
|
||||
|
||||
All orders, whether off-chain or on-chain, can only be cancelled on-chain. The following contract functions are used to cancel individual ERC721 and ERC1155 orders.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Cancel a single ERC721 order by its nonce. The caller
|
||||
/// should be the maker of the order. Silently succeeds if
|
||||
/// an order with the same nonce has already been filled or
|
||||
/// cancelled.
|
||||
/// @param orderNonce The order nonce.
|
||||
function cancelERC721Order(uint256 orderNonce)
|
||||
external;
|
||||
|
||||
/// @dev Cancel a single ERC1155 order by its nonce. The caller
|
||||
/// should be the maker of the order. Silently succeeds if
|
||||
/// an order with the same nonce has already been filled or
|
||||
/// cancelled.
|
||||
/// @param orderNonce The order nonce.
|
||||
function cancelERC1155Order(uint256 orderNonce)
|
||||
external;
|
||||
|
||||
Note that if there are multiple outstanding orders with the same nonce, calling `cancelERC721Order` or `cancelERC1155Order` would cancel all those orders.
|
||||
The following functions can be used to cancel multiple orders.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Cancel multiple ERC721 orders by their nonces. The caller
|
||||
/// should be the maker of the orders. Silently succeeds if
|
||||
/// an order with the same nonce has already been filled or
|
||||
/// cancelled.
|
||||
/// @param orderNonces The order nonces.
|
||||
function batchCancelERC721Orders(uint256[] calldata orderNonces)
|
||||
external;
|
||||
|
||||
/// @dev Cancel multiple ERC1155 orders by their nonces. The caller
|
||||
/// should be the maker of the orders. Silently succeeds if
|
||||
/// an order with the same nonce has already been filled or
|
||||
/// cancelled.
|
||||
/// @param orderNonces The order nonces.
|
||||
function batchCancelERC1155Orders(uint256[] calldata orderNonces)
|
||||
external;
|
||||
|
||||
Fetching NFT Order Data
|
||||
=======================
|
||||
|
||||
To fetch collection-level NFT stats from 0x orders (e.g. floor price, total volume), checkout the following tools:
|
||||
|
||||
- `https://module.readme.io/reference/retrieve-collection-floor <https://module.readme.io/reference/retrieve-collection-floor>`_
|
||||
- `https://api.reservoir.tools/#/2.%20Aggregator/getEventsCollectionsFlooraskV1 <https://api.reservoir.tools/#/2.%20Aggregator/getEventsCollectionsFlooraskV1>`_
|
||||
|
||||
These tools are not 0x specific but NFT data is somewhat universal so these tools should do the trick.
|
@ -1,17 +0,0 @@
|
||||
############
|
||||
Smart Nonces
|
||||
############
|
||||
|
||||
The `nonce` field in the order is a number the maker chooses to ensure uniqueness of the order, but it also has some other functions:
|
||||
- To identify the order (in addition to the caller/maker) in cancellation functions.
|
||||
- To identify the order when checking/updating its filled state.
|
||||
- To potentially reuse EVM storage slots that mark an order as filled, which can provide significant gas savings (~15k) when filling or cancelling the order.
|
||||
|
||||
**Gas Optimized Nonces**
|
||||
|
||||
The protocol marks ERC721 orders as filled when they either get cancelled or filled. Instead of always using a completely new storage slot for each order from a maker, the upper 248 bits of the nonce will identify the storage slot/bucket/status vector to be used and the lower 8 bits of the nonce will identify the bit offset in that slot (each slot is also 256 bits) which will be flipped from 0 to 1 when the order is cancelled or filled.
|
||||
|
||||
.. image:: ./_static/img/smart_nonce_diagram.webp
|
||||
:width: 600
|
||||
|
||||
To take advantage of this gas optimization, makers should reuse the upper 248 bits of their nonce across up to 256 different orders, varying the value of the lower 8 bits between them.
|
@ -1,28 +1,39 @@
|
||||
0x Protocol
|
||||
===========
|
||||
|
||||
0x Protocol is the trusted open source settlement layer for the permissionless global exchange of value.
|
||||
|
||||
This documentation is aimed to serve as the canonical technical documentation for 0x Protocol and the system of smart contracts that make up its full functionality. The structure of this documentation is as follows:
|
||||
|
||||
- Architectural Overview of the whole system of smart contracts that 0x Protocol is comprised of.
|
||||
- Subsections will provide a deep dive into each contracts
|
||||
- Tutorial and tools to get started building with/on top of 0x Protocol
|
||||
|
||||
To learn more about why 0x Protocol was created, read the whitepaper `here <https://github.com/0xProject/whitepaper/blob/master/0x_white_paper.pdf>`_ and at `0xProtocol.org <https://0xProtocol.org>`_.
|
||||
|
||||
All code is open sourced on `GitHub <https://github.com/0xProject/protocol>`_.
|
||||
|
||||
Connect with the community on our `Forum <https://forum.0xProtocol.org/>`_, `Discord <https://discord.com/invite/official0x>`_, `Reddit <https://www.reddit.com/r/0xProject/>`_, and `Twitter <https://twitter.com/zeroexprotocol>`_.
|
||||
0x is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets.
|
||||
Learn more about 0x Labs at `0x.org <https://0x.org>`_. Check out our code on `GitHub <https://github.com/0xProject/protocol>`_.
|
||||
Connect with the community on our `Forum <https://forum.0x.org/>`_ and `Reddit <https://www.reddit.com/r/0xProject/>`_.
|
||||
Chat with our team privately on `Discord <https://discord.com/invite/d3FTX3M>`_ or publicly on `Twitter <https://twitter.com/0xproject>`_.
|
||||
|
||||
|
||||
.. image:: ./_static/img/logo.png
|
||||
:width: 60%
|
||||
.. image:: ./_static/img/logo.svg
|
||||
:width: 20%
|
||||
:alt: 0x Protocol logo
|
||||
:align: center
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 2
|
||||
:caption: Basics
|
||||
|
||||
basics/orders.rst
|
||||
basics/functions.rst
|
||||
basics/events.rst
|
||||
basics/allowances.rst
|
||||
basics/protocol_fees.rst
|
||||
basics/addresses.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Advanced
|
||||
|
||||
advanced/mtx.rst
|
||||
advanced/erc20_transformations.rst
|
||||
advanced/plp.rst
|
||||
advanced/uniswap.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Architecture
|
||||
|
||||
architecture/overview.rst
|
||||
@ -34,36 +45,19 @@ Connect with the community on our `Forum <https://forum.0xProtocol.org/>`_, `Dis
|
||||
architecture/transformer_deployer.rst
|
||||
architecture/fee_collectors.rst
|
||||
architecture/plp_sandbox.rst
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Basics
|
||||
:maxdepth: 2
|
||||
:caption: ZRX Tokenomics
|
||||
|
||||
basics/orders.rst
|
||||
basics/functions.rst
|
||||
basics/events.rst
|
||||
basics/allowances.rst
|
||||
basics/protocol_fees.rst
|
||||
basics/addresses.rst
|
||||
tokenomics/research.rst
|
||||
tokenomics/staking.md
|
||||
tokenomics/staking_reward_formula.rst
|
||||
tokenomics/governance.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Advanced
|
||||
|
||||
advanced/mtx.rst
|
||||
advanced/erc20_transformations.rst
|
||||
advanced/plp.rst
|
||||
advanced/uniswap.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Guide
|
||||
|
||||
guides/nft_guide.rst
|
||||
guides/smart_nonce.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 2
|
||||
:caption: Additional Material
|
||||
|
||||
additional/audits.rst
|
||||
@ -77,9 +71,9 @@ Connect with the community on our `Forum <https://forum.0xProtocol.org/>`_, `Dis
|
||||
:maxdepth: 1
|
||||
:caption: Connect
|
||||
|
||||
0x Protocol <https://0xProtocol.org>
|
||||
0x Labs <https://0x.org>
|
||||
GitHub <https://github.com/0xProject/protocol>
|
||||
Forum <https://forum.0xProtocol.org/>
|
||||
Forum <https://forum.0x.org/>
|
||||
Reddit <https://www.reddit.com/r/0xProject/>
|
||||
Discord <https://discord.com/invite/official0x>
|
||||
Twitter <https://twitter.com/zeroexprotocol>
|
||||
Discord <https://discord.com/invite/d3FTX3M>
|
||||
Twitter <https://twitter.com/0xproject>
|
@ -1,4 +1,3 @@
|
||||
six
|
||||
sphinx==3.5.4
|
||||
sphinx-markdown-tables
|
||||
jinja2<3.1
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user