chore: Prune old contracts (#304)
Prune exchange-libs deploy migrations at specific address remove exchange-libs, moving LibMath into Utils Remove staking order-utils multisig and remaining asset-proxy
This commit is contained in:
45
README.md
45
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
---
|
||||
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. For more information on how it works, check out the [0x protocol specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. For more information on how it works, check out the [0x protocol specification](https://protocol.0x.org/).
|
||||
|
||||
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
|
||||
|
||||
@@ -15,40 +15,31 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
|
||||
|
||||
## Packages
|
||||
|
||||
Visit our [developer portal](https://0x.org/docs/tools/order-utils) for a comprehensive list of core & community maintained packages. All packages maintained with this monorepo are listed below.
|
||||
Visit our [developer portal](https://0x.org/docs/) for a comprehensive list of core & community maintained packages. All packages maintained with this monorepo are listed below.
|
||||
|
||||
### Solidity Packages
|
||||
|
||||
These packages are all under development. See [/contracts/README.md](/contracts/README.md) for a list of deployed packages.
|
||||
|
||||
| Package | Version | Description |
|
||||
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [](https://www.npmjs.com/package/@0x/contracts-asset-proxy) | [`AssetProxy`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy) contracts used within the protocol |
|
||||
| [`@0x/contracts-erc20`](/contracts/erc20) | [](https://www.npmjs.com/package/@0x/contracts-erc20) | Implementations of various ERC20 tokens |
|
||||
| [`@0x/contracts-erc721`](/contracts/erc721) | [](https://www.npmjs.com/package/@0x/contracts-erc721) | Implementations of various ERC721 tokens |
|
||||
| [`@0x/contracts-erc1155`](/contracts/erc1155) | [](https://www.npmjs.com/package/@0x/contracts-erc1155) | Implementations of various ERC1155 tokens |
|
||||
| [`@0x/contracts-exchange`](/contracts/exchange) | [](https://www.npmjs.com/package/@0x/contracts-exchange) | The [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract used for settling trades within the protocol |
|
||||
| [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder) | A [`Forwarder`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract used to simplify UX for interacting with the protocol |
|
||||
| [`@0x/contracts-exchange-libs`](/contracts/exchange-libs) | [](https://www.npmjs.com/package/@0x/contracts-exchange-libs) | Protocol specific libraries used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract |
|
||||
| [`@0x/contracts-extensions`](/contracts/extensions) | [](https://www.npmjs.com/package/@0x/contracts-extensions) | Contracts that interact with and extend the functionality of the core protocol |
|
||||
| [`@0x/contracts-multisig`](/contracts/multisig) | [](https://www.npmjs.com/package/@0x/contracts-multisig) | Various implementations of multisignature wallets, including the [`AssetProxyOwner`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxyowner) contract that has permissions to upgrade the protocol |
|
||||
| [`@0x/contracts-test-utils`](/contracts/test-utils) | [](https://www.npmjs.com/package/@0x/contracts-test-utils) | TypeScript/Javascript shared utilities used for testing contracts |
|
||||
| [`@0x/contracts-utils`](/contracts/utils) | [](https://www.npmjs.com/package/@0x/contracts-utils) | Generic libraries and utilities used throughout all of the contracts |
|
||||
| [`@0x/contracts-coordinator`](/contracts/coordinator) | [](https://www.npmjs.com/package/@0x/contracts-coordinator) | A contract that allows users to execute 0x transactions with permission from a Coordinator |
|
||||
| [`@0x/contracts-dev-utils`](/contracts/dev-utils) | [](https://www.npmjs.com/package/@0x/contracts-dev-utils) | A contract contains utility functions for developers (such as validating many orders using a single eth_call) |
|
||||
| [`@0x/contracts-staking`](/contracts/staking) | [](https://www.npmjs.com/package/@0x/contracts-staking) | Implements the stake-based liquidity incentives defined by [`ZEIP-31`](https://github.com/0xProject/ZEIPs/issues/31) |
|
||||
| Package | Version | Description |
|
||||
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| [`@0x/contracts-zero-ex`](/contracts/zero-ex) | [](https://www.npmjs.com/package/@0x/contracts-zero-ex) | The contracts used for settling trades within the protocol |
|
||||
| [`@0x/contracts-erc20`](/contracts/erc20) | [](https://www.npmjs.com/package/@0x/contracts-erc20) | Implementations of various ERC20 tokens |
|
||||
| [`@0x/contracts-test-utils`](/contracts/test-utils) | [](https://www.npmjs.com/package/@0x/contracts-test-utils) | TypeScript/Javascript shared utilities used for testing contracts |
|
||||
| [`@0x/contracts-utils`](/contracts/utils) | [](https://www.npmjs.com/package/@0x/contracts-utils) | Generic libraries and utilities used throughout all of the contracts |
|
||||
|
||||
### TypeScript/Javascript Packages
|
||||
|
||||
#### 0x-specific packages
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| [`@0x/asset-swapper`](/packages/asset-swapper) | [](https://www.npmjs.com/package/@0x/asset-swapper) | Package used to find and create aggregated swaps |
|
||||
| [`@0x/protocol-utils`](/packages/protocol-utils) | [](https://www.npmjs.com/package/@0x/protocol-utils) | A set of utilities for generating, parsing, signing and validating 0x orders |
|
||||
| [`@0x/contract-addresses`](/packages/contract-addresses) | [](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network. |
|
||||
| [`@0x/contract-wrappers`](/packages/contract-wrappers) | [](https://www.npmjs.com/package/@0x/contract-wrappers) | JS/TS wrappers for interacting with the 0x smart contracts |
|
||||
| [`@0x/order-utils`](/packages/order-utils) | [](https://www.npmjs.com/package/@0x/order-utils) | A set of utilities for generating, parsing, signing and validating 0x orders |
|
||||
| [`@0x/migrations`](/packages/migrations) | [](https://www.npmjs.com/package/@0x/migrations) | Migration tool for deploying 0x smart contracts on private testnets |
|
||||
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts | |
|
||||
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts | |
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -92,7 +83,7 @@ yarn build
|
||||
To build a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contract-wrappers yarn build
|
||||
PKG=@0x/asset-swapper yarn build
|
||||
```
|
||||
|
||||
To build all contracts packages:
|
||||
@@ -115,7 +106,7 @@ To watch a specific package and all it's dependent packages:
|
||||
PKG=[NPM_PACKAGE_NAME] yarn watch
|
||||
|
||||
e.g
|
||||
PKG=@0x/contract-wrappers yarn watch
|
||||
PKG=@0x/asset-swapper yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
@@ -129,7 +120,7 @@ yarn clean
|
||||
Clean a specific package
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn clean
|
||||
PKG=@0x/asset-swapper yarn clean
|
||||
```
|
||||
|
||||
### Rebuild
|
||||
@@ -143,7 +134,7 @@ yarn rebuild
|
||||
To re-build (clean & build) a specific package & it's deps:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contract-wrappers yarn rebuild
|
||||
PKG=@0x/asset-swapper yarn rebuild
|
||||
```
|
||||
|
||||
### Lint
|
||||
@@ -157,7 +148,7 @@ yarn lint
|
||||
Lint a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contract-wrappers yarn lint
|
||||
PKG=@0x/asset-swapper yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
@@ -171,7 +162,7 @@ yarn test
|
||||
Run a specific package's test:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contract-wrappers yarn test
|
||||
PKG=@0x/asset-swapper yarn test
|
||||
```
|
||||
|
||||
Run all contracts packages tests:
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
#### Deployed Contract Packages
|
||||
|
||||
| Contract | Package | Version | Git Tag |
|
||||
| --------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| AssetProxyOwner | [`@0x/contracts-multisig`](/contracts/multisig) | [v1.0.2](https://www.npmjs.com/package/@0x/contracts-multisig/v/1.0.2) | [@0x/contracts-multisig@1.0.2](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-multisig@1.0.2) |
|
||||
| ERC20Proxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
|
||||
| ERC721Proxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
|
||||
| Exchange | [`@0x/contracts-exchange`](/contracts/exchange) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange/v/1.0.1) | [@0x/contracts-exchange@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange@1.0.1) |
|
||||
| DutchAuction | [`@0x/contracts-extensions`](/contracts/extensions) | [v1.0.2](https://www.npmjs.com/package/@0x/contracts-extensions/v/1.0.2) | [@0x/contracts-extensions@1.0.2](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-extensions@1.0.2) |
|
||||
| Forwarder | [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder/v/1.0.1) | [@0x/contracts-exchange-forwarder@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange-forwarder@1.0.1) |
|
||||
| MultiAssetProxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
|
||||
| ZRXToken | [`@0x/contracts-erc20`](/contracts/erc20) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-erc20/v/1.0.1) | [@0x/contracts-erc20@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-erc20@1.0.1) |
|
||||
|
||||
#### Development
|
||||
|
||||
Building solidity files will update the contract artifact in `{package-name}/generated-artifacts/{contract}.json`, but does not automatically update the `contract-artifacts` or `contract-wrappers` packages, which are generated from the artifact JSON. See `contract-artifacts/README.md` for instructions on updating these packages.
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# Contracts testing options
|
||||
|
||||
## Revert stack traces
|
||||
|
||||
If you want to see helpful stack traces (incl. line number, code snippet) for smart contract reverts, run the tests with:
|
||||
|
||||
```
|
||||
yarn test:trace
|
||||
```
|
||||
|
||||
**Note:** This currently slows down the test runs and is therefore not enabled by default.
|
||||
|
||||
## Backing Ethereum node
|
||||
|
||||
By default, our tests run against an in-process [Ganache](https://github.com/trufflesuite/ganache-core) instance. In order to run the tests against [Geth](https://github.com/ethereum/go-ethereum), first follow the instructions in the README for the devnet package to start the devnet Geth node. Then run:
|
||||
|
||||
```bash
|
||||
TEST_PROVIDER=geth yarn test
|
||||
```
|
||||
|
||||
## Code coverage
|
||||
|
||||
In order to see the Solidity code coverage output generated by `@0x/sol-coverage`, run:
|
||||
|
||||
```
|
||||
yarn test:coverage
|
||||
```
|
||||
|
||||
## Gas profiler
|
||||
|
||||
In order to profile the gas costs for a specific smart contract call/transaction, you can run the tests in `profiler` mode.
|
||||
|
||||
**Note:** Traces emitted by ganache have incorrect gas costs so we recommend using Geth for profiling.
|
||||
|
||||
```
|
||||
TEST_PROVIDER=geth yarn test:profiler
|
||||
```
|
||||
|
||||
You'll see a warning that you need to explicitly enable and disable the profiler before and after the block of code you want to profile.
|
||||
|
||||
```typescript
|
||||
import { profiler } from './utils/profiler';
|
||||
profiler.start();
|
||||
// Some call to a smart contract
|
||||
profiler.stop();
|
||||
```
|
||||
|
||||
Without explicitly starting and stopping the profiler, the profiler output will be too busy, and therefore unusable.
|
||||
@@ -1,10 +0,0 @@
|
||||
# Blacklist all files
|
||||
.*
|
||||
*
|
||||
# Whitelist lib
|
||||
!lib/**/*
|
||||
# Whitelist Solidity contracts
|
||||
!contracts/src/**/*
|
||||
# Blacklist tests in lib
|
||||
/lib/test/*
|
||||
# Package specific ignore
|
||||
@@ -1,2 +0,0 @@
|
||||
# solhint can't parse `abi.decode` syntax.
|
||||
contracts/src/ERC1155Proxy.sol
|
||||
@@ -1,904 +0,0 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1629079369,
|
||||
"version": "3.7.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1628665757,
|
||||
"version": "3.7.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1628225642,
|
||||
"version": "3.7.17",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1624356181,
|
||||
"version": "3.7.16",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1623382456,
|
||||
"version": "3.7.15",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1622609597,
|
||||
"version": "3.7.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1621944788,
|
||||
"version": "3.7.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1621600614,
|
||||
"version": "3.7.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1620214333,
|
||||
"version": "3.7.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1619596077,
|
||||
"version": "3.7.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1617311315,
|
||||
"version": "3.7.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1616005394,
|
||||
"version": "3.7.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1614141718,
|
||||
"version": "3.7.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1612950500,
|
||||
"version": "3.7.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1611648096,
|
||||
"version": "3.7.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1610510890,
|
||||
"version": "3.7.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1609802516,
|
||||
"version": "3.7.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608692071,
|
||||
"version": "3.7.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1608245516,
|
||||
"version": "3.7.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.7.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix Bancor support of ETH",
|
||||
"pr": 88
|
||||
}
|
||||
],
|
||||
"timestamp": 1608105788
|
||||
},
|
||||
{
|
||||
"timestamp": 1607485227,
|
||||
"version": "3.6.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1607381756,
|
||||
"version": "3.6.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1606961263,
|
||||
"version": "3.6.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1605763885,
|
||||
"version": "3.6.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1605302002,
|
||||
"version": "3.6.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1604385937,
|
||||
"version": "3.6.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1604376968,
|
||||
"version": "3.6.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1604355662,
|
||||
"version": "3.6.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1603851023,
|
||||
"version": "3.6.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.6.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `SwerveBridge` and `SnowSwapBridge` (duplicate of `CurveBridge`)",
|
||||
"pr": 2707
|
||||
}
|
||||
],
|
||||
"timestamp": 1603833198
|
||||
},
|
||||
{
|
||||
"version": "3.5.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Update `CurveBridge` to support more varied curves",
|
||||
"pr": 2633
|
||||
},
|
||||
{
|
||||
"note": "Export DexForwarderBridgeContract",
|
||||
"pr": 2656
|
||||
},
|
||||
{
|
||||
"note": "Add BancorBridge and IBancorNetwork, ",
|
||||
"pr": 2650
|
||||
},
|
||||
{
|
||||
"note": "Added `MStableBridge`",
|
||||
"pr": 2662
|
||||
},
|
||||
{
|
||||
"note": "Added `MooniswapBridge`",
|
||||
"pr": 2675
|
||||
},
|
||||
{
|
||||
"note": "Reworked `KyberBridge`",
|
||||
"pr": 2683
|
||||
},
|
||||
{
|
||||
"note": "Added `CreamBridge`",
|
||||
"pr": 2715
|
||||
},
|
||||
{
|
||||
"note": "Added `ShellBridge`",
|
||||
"pr": 2722
|
||||
},
|
||||
{
|
||||
"note": "Added `DODOBridge`",
|
||||
"pr": 2701
|
||||
}
|
||||
],
|
||||
"timestamp": 1603265572
|
||||
},
|
||||
{
|
||||
"version": "3.4.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix instability with DFB.",
|
||||
"pr": 2616
|
||||
},
|
||||
{
|
||||
"note": "Add `BalancerBridge`",
|
||||
"pr": 2613
|
||||
}
|
||||
],
|
||||
"timestamp": 1594788383
|
||||
},
|
||||
{
|
||||
"version": "3.3.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals.",
|
||||
"pr": 2512
|
||||
},
|
||||
{
|
||||
"note": "Emit `ERC20BridgeTransfer` events in bridges.",
|
||||
"pr": 2512
|
||||
},
|
||||
{
|
||||
"note": "Change names of `ERC20BridgeTransfer` args to be less ambiguous.",
|
||||
"pr": 2524
|
||||
},
|
||||
{
|
||||
"note": "Added `MixinGasToken` allowing Gas Tokens to be freed",
|
||||
"pr": 2523
|
||||
},
|
||||
{
|
||||
"note": "Add `DexForwaderBridge` bridge contract.",
|
||||
"pr": 2525
|
||||
},
|
||||
{
|
||||
"note": "Add `UniswapV2Bridge` bridge contract.",
|
||||
"pr": 2590
|
||||
},
|
||||
{
|
||||
"note": "Add Gas Token freeing to `DexForwarderBridge` contract.",
|
||||
"pr": 2536
|
||||
}
|
||||
],
|
||||
"timestamp": 1592969527
|
||||
},
|
||||
{
|
||||
"timestamp": 1583220306,
|
||||
"version": "3.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1582837861,
|
||||
"version": "3.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1582677073,
|
||||
"version": "3.2.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1582623685,
|
||||
"version": "3.2.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1581748629,
|
||||
"version": "3.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add more types and functions to `IDydx`",
|
||||
"pr": 2466
|
||||
},
|
||||
{
|
||||
"note": "Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx`",
|
||||
"pr": 2466
|
||||
},
|
||||
{
|
||||
"note": "Fix broken tests.",
|
||||
"pr": 2462
|
||||
},
|
||||
{
|
||||
"note": "Remove dependency on `@0x/contracts-dev-utils`",
|
||||
"pr": 2462
|
||||
},
|
||||
{
|
||||
"note": "Add asset data decoding functions",
|
||||
"pr": 2462
|
||||
},
|
||||
{
|
||||
"note": "Add `setOperators()` to `IDydx`",
|
||||
"pr": 2462
|
||||
}
|
||||
],
|
||||
"timestamp": 1581204851
|
||||
},
|
||||
{
|
||||
"timestamp": 1580988106,
|
||||
"version": "3.1.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1580811564,
|
||||
"version": "3.1.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1579682890,
|
||||
"version": "3.1.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Integration tests for DydxBridge with ERC20BridgeProxy.",
|
||||
"pr": 2401
|
||||
},
|
||||
{
|
||||
"note": "Fix `UniswapBridge` token -> token transfer call.",
|
||||
"pr": 2412
|
||||
},
|
||||
{
|
||||
"note": "Fix `KyberBridge` incorrect `minConversionRate` calculation.",
|
||||
"pr": 2412
|
||||
}
|
||||
],
|
||||
"timestamp": 1578272714
|
||||
},
|
||||
{
|
||||
"timestamp": 1576540892,
|
||||
"version": "3.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1575931811,
|
||||
"version": "3.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Implement `KyberBridge`.",
|
||||
"pr": 2352
|
||||
},
|
||||
{
|
||||
"note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
|
||||
"pr": 2330
|
||||
},
|
||||
{
|
||||
"note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract",
|
||||
"pr": 2034
|
||||
},
|
||||
{
|
||||
"note": "Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable",
|
||||
"pr": 2019
|
||||
},
|
||||
{
|
||||
"note": "Remove `LibAssetProxyIds` contract",
|
||||
"pr": 2055
|
||||
},
|
||||
{
|
||||
"note": "Compile and export all contracts, artifacts, and wrappers by default",
|
||||
"pr": 2055
|
||||
},
|
||||
{
|
||||
"note": "Remove unused dependency on IAuthorizable in IAssetProxy",
|
||||
"pr": 1910
|
||||
},
|
||||
{
|
||||
"note": "Add `ERC20BridgeProxy`",
|
||||
"pr": 2220
|
||||
},
|
||||
{
|
||||
"note": "Add `Eth2DaiBridge`",
|
||||
"pr": 2221
|
||||
},
|
||||
{
|
||||
"note": "Add `UniswapBridge`",
|
||||
"pr": 2233
|
||||
},
|
||||
{
|
||||
"note": "Replaced `SafeMath` with `LibSafeMath`",
|
||||
"pr": 2254
|
||||
}
|
||||
],
|
||||
"timestamp": 1575296764
|
||||
},
|
||||
{
|
||||
"version": "2.3.0-beta.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Implement `KyberBridge`.",
|
||||
"pr": 2352
|
||||
},
|
||||
{
|
||||
"note": "Implement `DydxBridge`.",
|
||||
"pr": 2365
|
||||
}
|
||||
],
|
||||
"timestamp": 1575290197
|
||||
},
|
||||
{
|
||||
"version": "2.3.0-beta.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1574238768
|
||||
},
|
||||
{
|
||||
"version": "2.3.0-beta.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
|
||||
"pr": 2330
|
||||
}
|
||||
],
|
||||
"timestamp": 1574030254
|
||||
},
|
||||
{
|
||||
"version": "2.3.0-beta.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract",
|
||||
"pr": 2034
|
||||
}
|
||||
],
|
||||
"timestamp": 1573159180
|
||||
},
|
||||
{
|
||||
"version": "2.3.0-beta.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable",
|
||||
"pr": 2019
|
||||
},
|
||||
{
|
||||
"note": "Remove `LibAssetProxyIds` contract",
|
||||
"pr": 2055
|
||||
},
|
||||
{
|
||||
"note": "Compile and export all contracts, artifacts, and wrappers by default",
|
||||
"pr": 2055
|
||||
},
|
||||
{
|
||||
"note": "Remove unused dependency on IAuthorizable in IAssetProxy",
|
||||
"pr": 1910
|
||||
},
|
||||
{
|
||||
"note": "Add `ERC20BridgeProxy`",
|
||||
"pr": 2220
|
||||
},
|
||||
{
|
||||
"note": "Add `Eth2DaiBridge`",
|
||||
"pr": 2221
|
||||
},
|
||||
{
|
||||
"note": "Add `UniswapBridge`",
|
||||
"pr": 2233
|
||||
},
|
||||
{
|
||||
"note": "Replaced `SafeMath` with `LibSafeMath`",
|
||||
"pr": 2254
|
||||
}
|
||||
],
|
||||
"timestamp": 1570135330
|
||||
},
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.2.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564607468
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.2.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.2.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `LibAssetProxyIds` contract",
|
||||
"pr": 1835
|
||||
},
|
||||
{
|
||||
"note": "Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases.",
|
||||
"pr": 1852
|
||||
},
|
||||
{
|
||||
"note": "Implement StaticCallProxy",
|
||||
"pr": 1863
|
||||
}
|
||||
],
|
||||
"timestamp": 1563006338
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557799313,
|
||||
"version": "2.1.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Update tests to use contract-built-in `awaitTransactionSuccessAsync`",
|
||||
"pr": 1797
|
||||
},
|
||||
{
|
||||
"note": "Make `ERC721Wrapper.setApprovalForAll()` take an owner address instead of a token ID",
|
||||
"pr": 1819
|
||||
},
|
||||
{
|
||||
"note": "Automatically set unlimited proxy allowances in `ERC721.setBalancesAndAllowancesAsync()`",
|
||||
"pr": 1819
|
||||
},
|
||||
{
|
||||
"note": "Add `setProxyAllowanceForAllAsync()` to `ERC1155ProxyWrapper`.",
|
||||
"pr": 1819
|
||||
}
|
||||
],
|
||||
"timestamp": 1557507213
|
||||
},
|
||||
{
|
||||
"version": "2.1.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1554997931
|
||||
},
|
||||
{
|
||||
"version": "2.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Run Web3ProviderEngine without excess block polling",
|
||||
"pr": 1695
|
||||
}
|
||||
],
|
||||
"timestamp": 1553183790
|
||||
},
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Do not reexport external dependencies",
|
||||
"pr": 1682
|
||||
},
|
||||
{
|
||||
"note": "Add ERC1155Proxy",
|
||||
"pr": 1661
|
||||
},
|
||||
{
|
||||
"note": "Bumped solidity version to ^0.5.5",
|
||||
"pr": 1701
|
||||
},
|
||||
{
|
||||
"note": "Integration testing for ERC1155Proxy",
|
||||
"pr": 1673
|
||||
}
|
||||
],
|
||||
"timestamp": 1553091633
|
||||
},
|
||||
{
|
||||
"timestamp": 1551479279,
|
||||
"version": "1.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1551299797,
|
||||
"version": "1.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1551220833,
|
||||
"version": "1.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1551130135,
|
||||
"version": "1.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1549733923,
|
||||
"version": "1.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1549547375
|
||||
},
|
||||
{
|
||||
"version": "1.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fake publish to enable pinning"
|
||||
}
|
||||
],
|
||||
"timestamp": 1549504360
|
||||
},
|
||||
{
|
||||
"timestamp": 1549452781,
|
||||
"version": "1.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1549373905,
|
||||
"version": "1.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Move all AssetProxy contracts out of contracts-protocol to new package",
|
||||
"pr": 1539
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,362 +0,0 @@
|
||||
<!--
|
||||
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.7.19 - _August 16, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.18 - _August 11, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.17 - _August 6, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.16 - _June 22, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.15 - _June 11, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.14 - _June 2, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.13 - _May 25, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.12 - _May 21, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.11 - _May 5, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.10 - _April 28, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.9 - _April 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.8 - _March 17, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.7 - _February 24, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.6 - _February 10, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.5 - _January 26, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.4 - _January 13, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.3 - _January 4, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.2 - _December 23, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.1 - _December 17, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.7.0 - _December 16, 2020_
|
||||
|
||||
* Fix Bancor support of ETH (#88)
|
||||
|
||||
## v3.6.9 - _December 9, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.8 - _December 7, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.7 - _December 3, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.6 - _November 19, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.5 - _November 13, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.4 - _November 3, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.3 - _November 3, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.2 - _November 2, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.1 - _October 28, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.6.0 - _October 27, 2020_
|
||||
|
||||
* Add `SwerveBridge` and `SnowSwapBridge` (duplicate of `CurveBridge`) (#2707)
|
||||
|
||||
## v3.5.0 - _October 21, 2020_
|
||||
|
||||
* Update `CurveBridge` to support more varied curves (#2633)
|
||||
* Export DexForwarderBridgeContract (#2656)
|
||||
* Add BancorBridge and IBancorNetwork, (#2650)
|
||||
* Added `MStableBridge` (#2662)
|
||||
* Added `MooniswapBridge` (#2675)
|
||||
* Reworked `KyberBridge` (#2683)
|
||||
* Added `CreamBridge` (#2715)
|
||||
* Added `ShellBridge` (#2722)
|
||||
* Added `DODOBridge` (#2701)
|
||||
|
||||
## v3.4.0 - _July 15, 2020_
|
||||
|
||||
* Fix instability with DFB. (#2616)
|
||||
* Add `BalancerBridge` (#2613)
|
||||
|
||||
## v3.3.0 - _June 24, 2020_
|
||||
|
||||
* Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals. (#2512)
|
||||
* Emit `ERC20BridgeTransfer` events in bridges. (#2512)
|
||||
* Change names of `ERC20BridgeTransfer` args to be less ambiguous. (#2524)
|
||||
* Added `MixinGasToken` allowing Gas Tokens to be freed (#2523)
|
||||
* Add `DexForwaderBridge` bridge contract. (#2525)
|
||||
* Add `UniswapV2Bridge` bridge contract. (#2590)
|
||||
* Add Gas Token freeing to `DexForwarderBridge` contract. (#2536)
|
||||
|
||||
## v3.2.5 - _March 3, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.4 - _February 27, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.3 - _February 26, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.2 - _February 25, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.1 - _February 15, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.2.0 - _February 8, 2020_
|
||||
|
||||
* Add more types and functions to `IDydx` (#2466)
|
||||
* Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx` (#2466)
|
||||
* Fix broken tests. (#2462)
|
||||
* Remove dependency on `@0x/contracts-dev-utils` (#2462)
|
||||
* Add asset data decoding functions (#2462)
|
||||
* Add `setOperators()` to `IDydx` (#2462)
|
||||
|
||||
## v3.1.3 - _February 6, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.2 - _February 4, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.1 - _January 22, 2020_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.1.0 - _January 6, 2020_
|
||||
|
||||
* Integration tests for DydxBridge with ERC20BridgeProxy. (#2401)
|
||||
* Fix `UniswapBridge` token -> token transfer call. (#2412)
|
||||
* Fix `KyberBridge` incorrect `minConversionRate` calculation. (#2412)
|
||||
|
||||
## v3.0.2 - _December 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.1 - _December 9, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.0 - _December 2, 2019_
|
||||
|
||||
* Implement `KyberBridge`. (#2352)
|
||||
* Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
|
||||
* ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract (#2034)
|
||||
* Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable (#2019)
|
||||
* Remove `LibAssetProxyIds` contract (#2055)
|
||||
* Compile and export all contracts, artifacts, and wrappers by default (#2055)
|
||||
* Remove unused dependency on IAuthorizable in IAssetProxy (#1910)
|
||||
* Add `ERC20BridgeProxy` (#2220)
|
||||
* Add `Eth2DaiBridge` (#2221)
|
||||
* Add `UniswapBridge` (#2233)
|
||||
* Replaced `SafeMath` with `LibSafeMath` (#2254)
|
||||
|
||||
## v2.3.0-beta.4 - _December 2, 2019_
|
||||
|
||||
* Implement `KyberBridge`. (#2352)
|
||||
* Implement `DydxBridge`. (#2365)
|
||||
|
||||
## v2.3.0-beta.3 - _November 20, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.3.0-beta.2 - _November 17, 2019_
|
||||
|
||||
* Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
|
||||
|
||||
## v2.3.0-beta.1 - _November 7, 2019_
|
||||
|
||||
* ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract (#2034)
|
||||
|
||||
## v2.3.0-beta.0 - _October 3, 2019_
|
||||
|
||||
* Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable (#2019)
|
||||
* Remove `LibAssetProxyIds` contract (#2055)
|
||||
* Compile and export all contracts, artifacts, and wrappers by default (#2055)
|
||||
* Remove unused dependency on IAuthorizable in IAssetProxy (#1910)
|
||||
* Add `ERC20BridgeProxy` (#2220)
|
||||
* Add `Eth2DaiBridge` (#2221)
|
||||
* Add `UniswapBridge` (#2233)
|
||||
* Replaced `SafeMath` with `LibSafeMath` (#2254)
|
||||
|
||||
## v2.2.8 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.7 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.6 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.5 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.4 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.2.3 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.2 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.1 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.0 - _July 13, 2019_
|
||||
|
||||
* Add `LibAssetProxyIds` contract (#1835)
|
||||
* Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases. (#1852)
|
||||
* Implement StaticCallProxy (#1863)
|
||||
|
||||
## v2.1.5 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.4 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.3 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.2 - _May 10, 2019_
|
||||
|
||||
* Update tests to use contract-built-in `awaitTransactionSuccessAsync` (#1797)
|
||||
* Make `ERC721Wrapper.setApprovalForAll()` take an owner address instead of a token ID (#1819)
|
||||
* Automatically set unlimited proxy allowances in `ERC721.setBalancesAndAllowancesAsync()` (#1819)
|
||||
* Add `setProxyAllowanceForAllAsync()` to `ERC1155ProxyWrapper`. (#1819)
|
||||
|
||||
## v2.1.1 - _April 11, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.0 - _March 21, 2019_
|
||||
|
||||
* Run Web3ProviderEngine without excess block polling (#1695)
|
||||
|
||||
## v2.0.0 - _March 20, 2019_
|
||||
|
||||
* Do not reexport external dependencies (#1682)
|
||||
* Add ERC1155Proxy (#1661)
|
||||
* Bumped solidity version to ^0.5.5 (#1701)
|
||||
* Integration testing for ERC1155Proxy (#1673)
|
||||
|
||||
## v1.0.9 - _March 1, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.8 - _February 27, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.7 - _February 26, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.6 - _February 25, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.5 - _February 9, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.4 - _February 7, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.3 - _February 7, 2019_
|
||||
|
||||
* Fake publish to enable pinning
|
||||
|
||||
## v1.0.2 - _February 6, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.1 - _February 5, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.0 - _Invalid date_
|
||||
|
||||
* Move all AssetProxy contracts out of contracts-protocol to new package (#1539)
|
||||
@@ -1,47 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "MultiAssetProxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add MultiAssetProxy implementation",
|
||||
"pr": 1224,
|
||||
"networks": {
|
||||
"3": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6",
|
||||
"4": "0xb34cde0ad3a83d04abebc0b66e75196f22216621",
|
||||
"42": "0xf6313a772c222f51c28f2304c0703b8cf5428fd8"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ERC20Proxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e",
|
||||
"3": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
||||
"4": "0x3e809c563c15a295e832e37053798ddc8d6c8dab",
|
||||
"42": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ERC721Proxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x208e41fb445f1bb1b6780d58356e81405f3e6127",
|
||||
"3": "0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4",
|
||||
"4": "0x8e1ff02637cb5e39f2fa36c14706aa348b065b09",
|
||||
"42": "0x2a9127c745688a165106c11cd4d647d2220af821"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,73 +0,0 @@
|
||||
## AssetProxy
|
||||
|
||||
This package contains the implementations of all of the [`AssetProxy`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy) contracts available within the 0x protocol. These contracts are responsible for decoding the `assetData` sent to them and performing the actual transfer of assets. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
**Install**
|
||||
|
||||
```bash
|
||||
npm install @0x/contracts-asset-proxy --save
|
||||
```
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-asset-proxy yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-asset-proxy yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"artifactsDir": "./test/generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"useDockerisedSolc": false,
|
||||
"isOfflineMode": false,
|
||||
"shouldSaveStandardInput": true,
|
||||
"compilerSettings": {
|
||||
"evmVersion": "istanbul",
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000,
|
||||
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "../archive/Ownable.sol";
|
||||
import "../src/interfaces/IAssetProxy.sol";
|
||||
import "../src/interfaces/IAssetProxyDispatcher.sol";
|
||||
|
||||
|
||||
contract MixinAssetProxyDispatcher is
|
||||
Ownable,
|
||||
IAssetProxyDispatcher
|
||||
{
|
||||
// Mapping from Asset Proxy Id's to their respective Asset Proxy
|
||||
mapping (bytes4 => address) public assetProxies;
|
||||
|
||||
/// @dev Registers an asset proxy to its asset proxy id.
|
||||
/// Once an asset proxy is registered, it cannot be unregistered.
|
||||
/// @param assetProxy Address of new asset proxy to register.
|
||||
function registerAssetProxy(address assetProxy)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
// Ensure that no asset proxy exists with current id.
|
||||
bytes4 assetProxyId = IAssetProxy(assetProxy).getProxyId();
|
||||
address currentAssetProxy = assetProxies[assetProxyId];
|
||||
require(
|
||||
currentAssetProxy == address(0),
|
||||
"ASSET_PROXY_ALREADY_EXISTS"
|
||||
);
|
||||
|
||||
// Add asset proxy and log registration.
|
||||
assetProxies[assetProxyId] = assetProxy;
|
||||
emit AssetProxyRegistered(
|
||||
assetProxyId,
|
||||
assetProxy
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets an asset proxy.
|
||||
/// @param assetProxyId Id of the asset proxy.
|
||||
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
|
||||
function getAssetProxy(bytes4 assetProxyId)
|
||||
external
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return assetProxies[assetProxyId];
|
||||
}
|
||||
|
||||
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded for the asset.
|
||||
/// @param from Address to transfer token from.
|
||||
/// @param to Address to transfer token to.
|
||||
/// @param amount Amount of token to transfer.
|
||||
function _dispatchTransferFrom(
|
||||
bytes memory assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// Do nothing if no amount should be transferred.
|
||||
if (amount > 0 && from != to) {
|
||||
// Ensure assetData length is valid
|
||||
require(
|
||||
assetData.length > 3,
|
||||
"LENGTH_GREATER_THAN_3_REQUIRED"
|
||||
);
|
||||
|
||||
// Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons.
|
||||
bytes4 assetProxyId;
|
||||
assembly {
|
||||
assetProxyId := and(mload(
|
||||
add(assetData, 32)),
|
||||
0xFFFFFFFF00000000000000000000000000000000000000000000000000000000
|
||||
)
|
||||
}
|
||||
address assetProxy = assetProxies[assetProxyId];
|
||||
|
||||
// Ensure that assetProxy exists
|
||||
require(
|
||||
assetProxy != address(0),
|
||||
"ASSET_PROXY_DOES_NOT_EXIST"
|
||||
);
|
||||
|
||||
// We construct calldata for the `assetProxy.transferFrom` ABI.
|
||||
// The layout of this calldata is in the table below.
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// | -------- |--------|---------|-------------------------------------------- |
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | ** | assetData Contents |
|
||||
|
||||
assembly {
|
||||
/////// Setup State ///////
|
||||
// `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).
|
||||
let cdStart := mload(64)
|
||||
// `dataAreaLength` is the total number of words needed to store `assetData`
|
||||
// As-per the ABI spec, this value is padded up to the nearest multiple of 32,
|
||||
// and includes 32-bytes for length.
|
||||
let dataAreaLength := and(add(mload(assetData), 63), 0xFFFFFFFFFFFE0)
|
||||
// `cdEnd` is the end of the calldata for `assetProxy.transferFrom`.
|
||||
let cdEnd := add(cdStart, add(132, dataAreaLength))
|
||||
|
||||
|
||||
/////// Setup Header Area ///////
|
||||
// This area holds the 4-byte `transferFromSelector`.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
mstore(cdStart, 0xa85e59e400000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
/////// Setup Params Area ///////
|
||||
// Each parameter is padded to 32-bytes. The entire Params Area is 128 bytes.
|
||||
// Notes:
|
||||
// 1. The offset to `assetData` is the length of the Params Area (128 bytes).
|
||||
// 2. A 20-byte mask is applied to addresses to zero-out the unused bytes.
|
||||
mstore(add(cdStart, 4), 128)
|
||||
mstore(add(cdStart, 36), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
|
||||
mstore(add(cdStart, 68), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
|
||||
mstore(add(cdStart, 100), amount)
|
||||
|
||||
/////// Setup Data Area ///////
|
||||
// This area holds `assetData`.
|
||||
let dataArea := add(cdStart, 132)
|
||||
// solhint-disable-next-line no-empty-blocks
|
||||
for {} lt(dataArea, cdEnd) {} {
|
||||
mstore(dataArea, mload(assetData))
|
||||
dataArea := add(dataArea, 32)
|
||||
assetData := add(assetData, 32)
|
||||
}
|
||||
|
||||
/////// Call `assetProxy.transferFrom` using the constructed calldata ///////
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
assetProxy, // call address of asset proxy
|
||||
0, // don't send any ETH
|
||||
cdStart, // pointer to start of input
|
||||
sub(cdEnd, cdStart), // length of input
|
||||
cdStart, // write output over input
|
||||
512 // reserve 512 bytes for output
|
||||
)
|
||||
if iszero(success) {
|
||||
revert(cdStart, returndatasize())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "../archive/Ownable.sol";
|
||||
import "../src/interfaces/IAuthorizable.sol";
|
||||
|
||||
|
||||
contract MixinAuthorizable is
|
||||
Ownable,
|
||||
IAuthorizable
|
||||
{
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized {
|
||||
require(
|
||||
authorized[msg.sender],
|
||||
"SENDER_NOT_AUTHORIZED"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
mapping (address => bool) public authorized;
|
||||
address[] public authorities;
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
require(
|
||||
!authorized[target],
|
||||
"TARGET_ALREADY_AUTHORIZED"
|
||||
);
|
||||
|
||||
authorized[target] = true;
|
||||
authorities.push(target);
|
||||
emit AuthorizedAddressAdded(target, msg.sender);
|
||||
}
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
require(
|
||||
authorized[target],
|
||||
"TARGET_NOT_AUTHORIZED"
|
||||
);
|
||||
|
||||
delete authorized[target];
|
||||
for (uint256 i = 0; i < authorities.length; i++) {
|
||||
if (authorities[i] == target) {
|
||||
authorities[i] = authorities[authorities.length - 1];
|
||||
authorities.length -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit AuthorizedAddressRemoved(target, msg.sender);
|
||||
}
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
require(
|
||||
authorized[target],
|
||||
"TARGET_NOT_AUTHORIZED"
|
||||
);
|
||||
require(
|
||||
index < authorities.length,
|
||||
"INDEX_OUT_OF_BOUNDS"
|
||||
);
|
||||
require(
|
||||
authorities[index] == target,
|
||||
"AUTHORIZED_ADDRESS_MISMATCH"
|
||||
);
|
||||
|
||||
delete authorized[target];
|
||||
authorities[index] = authorities[authorities.length - 1];
|
||||
authorities.length -= 1;
|
||||
emit AuthorizedAddressRemoved(target, msg.sender);
|
||||
}
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
return authorities;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol";
|
||||
|
||||
|
||||
contract Ownable is
|
||||
IOwnable
|
||||
{
|
||||
address public owner;
|
||||
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(
|
||||
msg.sender == owner,
|
||||
"ONLY_CONTRACT_OWNER"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
function transferOwnership(address newOwner)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
if (newOwner != address(0)) {
|
||||
owner = newOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
|
||||
import "../archive/MixinAuthorizable.sol";
|
||||
import "./interfaces/IAssetProxy.sol";
|
||||
|
||||
|
||||
contract ERC1155Proxy is
|
||||
MixinAuthorizable,
|
||||
IAssetProxy
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
|
||||
|
||||
/// @dev Transfers batch of ERC1155 assets. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded with ERC1155 token address, array of ids, array of values, and callback data.
|
||||
/// @param from Address to transfer assets from.
|
||||
/// @param to Address to transfer assets to.
|
||||
/// @param amount Amount that will be multiplied with each element of `assetData.values` to scale the
|
||||
/// values that will be transferred.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
onlyAuthorized
|
||||
{
|
||||
// Decode params from `assetData`
|
||||
// solhint-disable indent
|
||||
(
|
||||
address erc1155TokenAddress,
|
||||
uint256[] memory ids,
|
||||
uint256[] memory values,
|
||||
bytes memory data
|
||||
) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address, uint256[], uint256[], bytes)
|
||||
);
|
||||
// solhint-enable indent
|
||||
|
||||
// Scale values up by `amount`
|
||||
uint256 length = values.length;
|
||||
uint256[] memory scaledValues = new uint256[](length);
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// We write the scaled values to an unused location in memory in order
|
||||
// to avoid copying over `ids` or `data`. This is possible if they are
|
||||
// identical to `values` and the offsets for each are pointing to the
|
||||
// same location in the ABI encoded calldata.
|
||||
scaledValues[i] = values[i].safeMul(amount);
|
||||
}
|
||||
|
||||
// Execute `safeBatchTransferFrom` call
|
||||
// Either succeeds or throws
|
||||
IERC1155(erc1155TokenAddress).safeBatchTransferFrom(
|
||||
from,
|
||||
to,
|
||||
ids,
|
||||
scaledValues,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "./interfaces/IAssetProxy.sol";
|
||||
import "./interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
contract ERC20BridgeProxy is
|
||||
IAssetProxy,
|
||||
Authorizable
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
// @dev Id of this proxy. Also the result of a successful bridge call.
|
||||
// bytes4(keccak256("ERC20Bridge(address,address,bytes)"))
|
||||
bytes4 constant private PROXY_ID = 0xdc1600f3;
|
||||
|
||||
/// @dev Calls a bridge contract to transfer `amount` of ERC20 from `from`
|
||||
/// to `to`. Asserts that the balance of `to` has increased by `amount`.
|
||||
/// @param assetData Abi-encoded data for this asset proxy encoded as:
|
||||
/// abi.encodeWithSelector(
|
||||
/// bytes4 PROXY_ID,
|
||||
/// address tokenAddress,
|
||||
/// address bridgeAddress,
|
||||
/// bytes bridgeData
|
||||
/// )
|
||||
/// @param from Address to transfer asset from.
|
||||
/// @param to Address to transfer asset to.
|
||||
/// @param amount Amount of asset to transfer.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
onlyAuthorized
|
||||
{
|
||||
// Extract asset data fields.
|
||||
(
|
||||
address tokenAddress,
|
||||
address bridgeAddress,
|
||||
bytes memory bridgeData
|
||||
) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address, address, bytes)
|
||||
);
|
||||
|
||||
// Remember the balance of `to` before calling the bridge.
|
||||
uint256 balanceBefore = balanceOf(tokenAddress, to);
|
||||
// Call the bridge, who should transfer `amount` of `tokenAddress` to
|
||||
// `to`.
|
||||
bytes4 success = IERC20Bridge(bridgeAddress).bridgeTransferFrom(
|
||||
tokenAddress,
|
||||
from,
|
||||
to,
|
||||
amount,
|
||||
bridgeData
|
||||
);
|
||||
// Bridge must return the proxy ID to indicate success.
|
||||
require(success == PROXY_ID, "BRIDGE_FAILED");
|
||||
// Ensure that the balance of `to` has increased by at least `amount`.
|
||||
require(
|
||||
balanceBefore.safeAdd(amount) <= balanceOf(tokenAddress, to),
|
||||
"BRIDGE_UNDERPAY"
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with this asset proxy.
|
||||
/// @return proxyId The proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4 proxyId)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
|
||||
/// @dev Retrieves the balance of `owner` for this asset.
|
||||
/// @return balance The balance of the ERC20 token being transferred by this
|
||||
/// asset proxy.
|
||||
function balanceOf(bytes calldata assetData, address owner)
|
||||
external
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
(address tokenAddress) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address)
|
||||
);
|
||||
return balanceOf(tokenAddress, owner);
|
||||
}
|
||||
|
||||
/// @dev Retrieves the balance of `owner` given an ERC20 address.
|
||||
/// @return balance The balance of the ERC20 token for `owner`.
|
||||
function balanceOf(address tokenAddress, address owner)
|
||||
private
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
return IERC20Token(tokenAddress).balanceOf(owner);
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "../archive/MixinAuthorizable.sol";
|
||||
|
||||
|
||||
contract ERC20Proxy is
|
||||
MixinAuthorizable
|
||||
{
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
|
||||
|
||||
// solhint-disable-next-line payable-fallback
|
||||
function ()
|
||||
external
|
||||
{
|
||||
assembly {
|
||||
// The first 4 bytes of calldata holds the function selector
|
||||
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// `transferFrom` will be called with the following parameters:
|
||||
// assetData Encoded byte array.
|
||||
// from Address to transfer asset from.
|
||||
// to Address to transfer asset to.
|
||||
// amount Amount of asset to transfer.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
|
||||
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
let start := mload(64)
|
||||
mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))
|
||||
mstore(add(start, 32), authorized_slot)
|
||||
|
||||
// Revert if authorized[msg.sender] == false
|
||||
if iszero(sload(keccak256(start, 64))) {
|
||||
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// `transferFrom`.
|
||||
// The function is marked `external`, so no abi decodeding is done for
|
||||
// us. Instead, we expect the `calldata` memory to contain the
|
||||
// following:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | ** | assetData Contents |
|
||||
//
|
||||
// (*): offset is computed from start of function parameters, so offset
|
||||
// by an additional 4 bytes in the calldata.
|
||||
//
|
||||
// (**): see table below to compute length of assetData Contents
|
||||
//
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 1 * 32 | function parameters: |
|
||||
// | | 4 | 12 + 20 | 1. token address |
|
||||
|
||||
// We construct calldata for the `token.transferFrom` ABI.
|
||||
// The layout of this calldata is in the table below.
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 3 * 32 | function parameters: |
|
||||
// | | 4 | | 1. from |
|
||||
// | | 36 | | 2. to |
|
||||
// | | 68 | | 3. amount |
|
||||
|
||||
/////// Read token address from calldata ///////
|
||||
// * The token address is stored in `assetData`.
|
||||
//
|
||||
// * The "offset to assetData" is stored at offset 4 in the calldata (table 1).
|
||||
// [assetDataOffsetFromParams = calldataload(4)]
|
||||
//
|
||||
// * Notes that the "offset to assetData" is relative to the "Params" area of calldata;
|
||||
// add 4 bytes to account for the length of the "Header" area (table 1).
|
||||
// [assetDataOffsetFromHeader = assetDataOffsetFromParams + 4]
|
||||
//
|
||||
// * The "token address" is offset 32+4=36 bytes into "assetData" (tables 1 & 2).
|
||||
// [tokenOffset = assetDataOffsetFromHeader + 36 = calldataload(4) + 4 + 36]
|
||||
let token := calldataload(add(calldataload(4), 40))
|
||||
|
||||
/////// Setup Header Area ///////
|
||||
// This area holds the 4-byte `transferFrom` selector.
|
||||
// Any trailing data in transferFromSelector will be
|
||||
// overwritten in the next `mstore` call.
|
||||
mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
/////// Setup Params Area ///////
|
||||
// We copy the fields `from`, `to` and `amount` in bulk
|
||||
// from our own calldata to the new calldata.
|
||||
calldatacopy(4, 36, 96)
|
||||
|
||||
/////// Call `token.transferFrom` using the calldata ///////
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
token, // call address of token contract
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
100, // length of input
|
||||
0, // write output over input
|
||||
32 // output size should be 32 bytes
|
||||
)
|
||||
|
||||
/////// Check return data. ///////
|
||||
// If there is no return data, we assume the token incorrectly
|
||||
// does not return a bool. In this case we expect it to revert
|
||||
// on failure, which was handled above.
|
||||
// If the token does return data, we require that it is a single
|
||||
// nonzero 32 bytes value.
|
||||
// So the transfer succeeded if the call succeeded and either
|
||||
// returned nothing, or returned a non-zero 32 byte value.
|
||||
success := and(success, or(
|
||||
iszero(returndatasize),
|
||||
and(
|
||||
eq(returndatasize, 32),
|
||||
gt(mload(0), 0)
|
||||
)
|
||||
))
|
||||
if success {
|
||||
return(0, 0)
|
||||
}
|
||||
|
||||
// Revert with `Error("TRANSFER_FAILED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Revert if undefined function is called
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "../archive/MixinAuthorizable.sol";
|
||||
|
||||
|
||||
contract ERC721Proxy is
|
||||
MixinAuthorizable
|
||||
{
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
|
||||
|
||||
// solhint-disable-next-line payable-fallback
|
||||
function ()
|
||||
external
|
||||
{
|
||||
assembly {
|
||||
// The first 4 bytes of calldata holds the function selector
|
||||
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// `transferFrom` will be called with the following parameters:
|
||||
// assetData Encoded byte array.
|
||||
// from Address to transfer asset from.
|
||||
// to Address to transfer asset to.
|
||||
// amount Amount of asset to transfer.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
|
||||
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
let start := mload(64)
|
||||
mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))
|
||||
mstore(add(start, 32), authorized_slot)
|
||||
|
||||
// Revert if authorized[msg.sender] == false
|
||||
if iszero(sload(keccak256(start, 64))) {
|
||||
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// `transferFrom`.
|
||||
// The function is marked `external`, so no abi decodeding is done for
|
||||
// us. Instead, we expect the `calldata` memory to contain the
|
||||
// following:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | ** | assetData Contents |
|
||||
//
|
||||
// (*): offset is computed from start of function parameters, so offset
|
||||
// by an additional 4 bytes in the calldata.
|
||||
//
|
||||
// (**): see table below to compute length of assetData Contents
|
||||
//
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 2 * 32 | function parameters: |
|
||||
// | | 4 | 12 + 20 | 1. token address |
|
||||
// | | 36 | | 2. tokenId |
|
||||
|
||||
// We construct calldata for the `token.transferFrom` ABI.
|
||||
// The layout of this calldata is in the table below.
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 3 * 32 | function parameters: |
|
||||
// | | 4 | | 1. from |
|
||||
// | | 36 | | 2. to |
|
||||
// | | 68 | | 3. tokenId |
|
||||
|
||||
// There exists only 1 of each token.
|
||||
// require(amount == 1, "INVALID_AMOUNT")
|
||||
if sub(calldataload(100), 1) {
|
||||
// Revert with `Error("INVALID_AMOUNT")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000000e494e56414c49445f414d4f554e540000000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
/////// Setup Header Area ///////
|
||||
// This area holds the 4-byte `transferFrom` selector.
|
||||
// Any trailing data in transferFromSelector will be
|
||||
// overwritten in the next `mstore` call.
|
||||
mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
/////// Setup Params Area ///////
|
||||
// We copy the fields `from` and `to` in bulk
|
||||
// from our own calldata to the new calldata.
|
||||
calldatacopy(4, 36, 64)
|
||||
|
||||
// Copy `tokenId` field from our own calldata to the new calldata.
|
||||
let assetDataOffset := calldataload(4)
|
||||
calldatacopy(68, add(assetDataOffset, 72), 32)
|
||||
|
||||
/////// Call `token.transferFrom` using the calldata ///////
|
||||
let token := calldataload(add(assetDataOffset, 40))
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
token, // call address of token contract
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
100, // length of input
|
||||
0, // write output to null
|
||||
0 // output size is 0 bytes
|
||||
)
|
||||
if success {
|
||||
return(0, 0)
|
||||
}
|
||||
|
||||
// Revert with `Error("TRANSFER_FAILED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Revert if undefined function is called
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,335 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "../archive/MixinAssetProxyDispatcher.sol";
|
||||
import "../archive/MixinAuthorizable.sol";
|
||||
|
||||
|
||||
contract MultiAssetProxy is
|
||||
MixinAssetProxyDispatcher,
|
||||
MixinAuthorizable
|
||||
{
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
|
||||
|
||||
// solhint-disable-next-line payable-fallback
|
||||
function ()
|
||||
external
|
||||
{
|
||||
// NOTE: The below assembly assumes that clients do some input validation and that the input is properly encoded according to the AbiV2 specification.
|
||||
// It is technically possible for inputs with very large lengths and offsets to cause overflows. However, this would make the calldata prohibitively
|
||||
// expensive and we therefore do not check for overflows in these scenarios.
|
||||
assembly {
|
||||
// The first 4 bytes of calldata holds the function selector
|
||||
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// `transferFrom` will be called with the following parameters:
|
||||
// assetData Encoded byte array.
|
||||
// from Address to transfer asset from.
|
||||
// to Address to transfer asset to.
|
||||
// amount Amount of asset to transfer.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
|
||||
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
mstore(0, caller)
|
||||
mstore(32, authorized_slot)
|
||||
|
||||
// Revert if authorized[msg.sender] == false
|
||||
if iszero(sload(keccak256(0, 64))) {
|
||||
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// `transferFrom`.
|
||||
// The function is marked `external`, so no abi decoding is done for
|
||||
// us. Instead, we expect the `calldata` memory to contain the
|
||||
// following:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | ** | assetData Contents |
|
||||
//
|
||||
// (*): offset is computed from start of function parameters, so offset
|
||||
// by an additional 4 bytes in the calldata.
|
||||
//
|
||||
// (**): see table below to compute length of assetData Contents
|
||||
//
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
|
||||
// Load offset to `assetData`
|
||||
let assetDataOffset := add(calldataload(4), 4)
|
||||
|
||||
// Load length in bytes of `assetData`
|
||||
let assetDataLength := calldataload(assetDataOffset)
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|-------------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | assetProxyId |
|
||||
// | Params | | 2 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to amounts (*) |
|
||||
// | | 36 | | 2. offset to nestedAssetData (*) |
|
||||
// | Data | | | amounts: |
|
||||
// | | 68 | 32 | amounts Length |
|
||||
// | | 100 | a | amounts Contents |
|
||||
// | | | | nestedAssetData: |
|
||||
// | | 100 + a | 32 | nestedAssetData Length |
|
||||
// | | 132 + a | b | nestedAssetData Contents (offsets) |
|
||||
// | | 132 + a + b | | nestedAssetData[0, ..., len] |
|
||||
|
||||
// Assert that the length of asset data:
|
||||
// 1. Must be at least 68 bytes (see table above)
|
||||
// 2. Must be a multiple of 32 (excluding the 4-byte selector)
|
||||
if or(lt(assetDataLength, 68), mod(sub(assetDataLength, 4), 32)) {
|
||||
// Revert with `Error("INVALID_ASSET_DATA_LENGTH")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x00000019494e56414c49445f41535345545f444154415f4c454e475448000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// End of asset data in calldata
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
let assetDataEnd := add(assetDataOffset, add(assetDataLength, 32))
|
||||
if gt(assetDataEnd, calldatasize()) {
|
||||
// Revert with `Error("INVALID_ASSET_DATA_END")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x00000016494e56414c49445f41535345545f444154415f454e44000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// In order to find the offset to `amounts`, we must add:
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
let amountsOffset := calldataload(add(assetDataOffset, 36))
|
||||
|
||||
// In order to find the offset to `nestedAssetData`, we must add:
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + 32 (amounts offset)
|
||||
let nestedAssetDataOffset := calldataload(add(assetDataOffset, 68))
|
||||
|
||||
// In order to find the start of the `amounts` contents, we must add:
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + amountsOffset
|
||||
// + 32 (amounts len)
|
||||
let amountsContentsStart := add(assetDataOffset, add(amountsOffset, 68))
|
||||
|
||||
// Load number of elements in `amounts`
|
||||
let amountsLen := calldataload(sub(amountsContentsStart, 32))
|
||||
|
||||
// In order to find the start of the `nestedAssetData` contents, we must add:
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
let nestedAssetDataContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, 68))
|
||||
|
||||
// Load number of elements in `nestedAssetData`
|
||||
let nestedAssetDataLen := calldataload(sub(nestedAssetDataContentsStart, 32))
|
||||
|
||||
// Revert if number of elements in `amounts` differs from number of elements in `nestedAssetData`
|
||||
if sub(amountsLen, nestedAssetDataLen) {
|
||||
// Revert with `Error("LENGTH_MISMATCH")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000000f4c454e4754485f4d49534d4154434800000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Copy `transferFrom` selector, offset to `assetData`, `from`, and `to` from calldata to memory
|
||||
calldatacopy(
|
||||
0, // memory can safely be overwritten from beginning
|
||||
0, // start of calldata
|
||||
100 // length of selector (4) and 3 params (32 * 3)
|
||||
)
|
||||
|
||||
// Overwrite existing offset to `assetData` with our own
|
||||
mstore(4, 128)
|
||||
|
||||
// Load `amount`
|
||||
let amount := calldataload(100)
|
||||
|
||||
// Calculate number of bytes in `amounts` contents
|
||||
let amountsByteLen := mul(amountsLen, 32)
|
||||
|
||||
// Initialize `assetProxyId` and `assetProxy` to 0
|
||||
let assetProxyId := 0
|
||||
let assetProxy := 0
|
||||
|
||||
// Loop through `amounts` and `nestedAssetData`, calling `transferFrom` for each respective element
|
||||
for {let i := 0} lt(i, amountsByteLen) {i := add(i, 32)} {
|
||||
|
||||
// Calculate the total amount
|
||||
let amountsElement := calldataload(add(amountsContentsStart, i))
|
||||
let totalAmount := mul(amountsElement, amount)
|
||||
|
||||
// Revert if `amount` != 0 and multiplication resulted in an overflow
|
||||
if iszero(or(
|
||||
iszero(amount),
|
||||
eq(div(totalAmount, amount), amountsElement)
|
||||
)) {
|
||||
// Revert with `Error("UINT256_OVERFLOW")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Write `totalAmount` to memory
|
||||
mstore(100, totalAmount)
|
||||
|
||||
// Load offset to `nestedAssetData[i]`
|
||||
let nestedAssetDataElementOffset := calldataload(add(nestedAssetDataContentsStart, i))
|
||||
|
||||
// In order to find the start of the `nestedAssetData[i]` contents, we must add:
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
// + nestedAssetDataElementOffset
|
||||
// + 32 (nestedAssetDataElement len)
|
||||
let nestedAssetDataElementContentsStart := add(
|
||||
assetDataOffset,
|
||||
add(
|
||||
nestedAssetDataOffset,
|
||||
add(nestedAssetDataElementOffset, 100)
|
||||
)
|
||||
)
|
||||
|
||||
// Load length of `nestedAssetData[i]`
|
||||
let nestedAssetDataElementLenStart := sub(nestedAssetDataElementContentsStart, 32)
|
||||
let nestedAssetDataElementLen := calldataload(nestedAssetDataElementLenStart)
|
||||
|
||||
// Revert if the `nestedAssetData` does not contain a 4 byte `assetProxyId`
|
||||
if lt(nestedAssetDataElementLen, 4) {
|
||||
// Revert with `Error("LENGTH_GREATER_THAN_3_REQUIRED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001e4c454e4754485f475245415445525f5448414e5f335f524551554952)
|
||||
mstore(96, 0x4544000000000000000000000000000000000000000000000000000000000000)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Load AssetProxy id
|
||||
let currentAssetProxyId := and(
|
||||
calldataload(nestedAssetDataElementContentsStart),
|
||||
0xffffffff00000000000000000000000000000000000000000000000000000000
|
||||
)
|
||||
|
||||
// Only load `assetProxy` if `currentAssetProxyId` does not equal `assetProxyId`
|
||||
// We do not need to check if `currentAssetProxyId` is 0 since `assetProxy` is also initialized to 0
|
||||
if sub(currentAssetProxyId, assetProxyId) {
|
||||
// Update `assetProxyId`
|
||||
assetProxyId := currentAssetProxyId
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
mstore(132, assetProxyId)
|
||||
mstore(164, assetProxies_slot)
|
||||
assetProxy := sload(keccak256(132, 64))
|
||||
}
|
||||
|
||||
// Revert if AssetProxy with given id does not exist
|
||||
if iszero(assetProxy) {
|
||||
// Revert with `Error("ASSET_PROXY_DOES_NOT_EXIST")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001a41535345545f50524f58595f444f45535f4e4f545f45584953540000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Copy `nestedAssetData[i]` from calldata to memory
|
||||
calldatacopy(
|
||||
132, // memory slot after `amounts[i]`
|
||||
nestedAssetDataElementLenStart, // location of `nestedAssetData[i]` in calldata
|
||||
add(nestedAssetDataElementLen, 32) // `nestedAssetData[i].length` plus 32 byte length
|
||||
)
|
||||
|
||||
// call `assetProxy.transferFrom`
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
assetProxy, // call address of asset proxy
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
add(164, nestedAssetDataElementLen), // length of input
|
||||
0, // write output over memory that won't be reused
|
||||
0 // don't copy output to memory
|
||||
)
|
||||
|
||||
// Revert with reason given by AssetProxy if `transferFrom` call failed
|
||||
if iszero(success) {
|
||||
returndatacopy(
|
||||
0, // copy to memory at 0
|
||||
0, // copy from return data at 0
|
||||
returndatasize() // copy all return data
|
||||
)
|
||||
revert(0, returndatasize())
|
||||
}
|
||||
}
|
||||
|
||||
// Return if no `transferFrom` calls reverted
|
||||
return(0, 0)
|
||||
}
|
||||
|
||||
// Revert if undefined function is called
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
|
||||
|
||||
// solhint-disable no-unused-vars
|
||||
contract StaticCallProxy {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("StaticCall(address,bytes,bytes32)"));
|
||||
|
||||
/// @dev Makes a staticcall to a target address and verifies that the data returned matches the expected return data.
|
||||
/// @param assetData Byte array encoded with staticCallTarget, staticCallData, and expectedCallResultHash
|
||||
/// @param from This value is ignored.
|
||||
/// @param to This value is ignored.
|
||||
/// @param amount This value is ignored.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
view
|
||||
{
|
||||
// Decode params from `assetData`
|
||||
(
|
||||
address staticCallTarget,
|
||||
bytes memory staticCallData,
|
||||
bytes32 expectedReturnDataHash
|
||||
) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address, bytes, bytes32)
|
||||
);
|
||||
|
||||
// Execute staticcall
|
||||
(bool success, bytes memory returnData) = staticCallTarget.staticcall(staticCallData);
|
||||
|
||||
// Revert with returned data if staticcall is unsuccessful
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(returnData, 32), mload(returnData))
|
||||
}
|
||||
}
|
||||
|
||||
// Revert if hash of return data is not as expected
|
||||
bytes32 returnDataHash = keccak256(returnData);
|
||||
require(
|
||||
expectedReturnDataHash == returnDataHash,
|
||||
"UNEXPECTED_STATIC_CALL_RESULT"
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IBalancerPool.sol";
|
||||
|
||||
|
||||
contract BalancerBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded addresses of the "from" token and Balancer pool.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data.
|
||||
(address fromTokenAddress, address poolAddress) = abi.decode(
|
||||
bridgeData,
|
||||
(address, address)
|
||||
);
|
||||
require(toTokenAddress != fromTokenAddress, "BalancerBridge/INVALID_PAIR");
|
||||
|
||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance);
|
||||
|
||||
// Sell all of this contract's `fromTokenAddress` token balance.
|
||||
(uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn(
|
||||
fromTokenAddress, // tokenIn
|
||||
fromTokenBalance, // tokenAmountIn
|
||||
toTokenAddress, // tokenOut
|
||||
amount, // minAmountOut
|
||||
uint256(-1) // maxPrice
|
||||
);
|
||||
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IBancorNetwork.sol";
|
||||
|
||||
|
||||
contract BancorBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct TransferState {
|
||||
address bancorNetworkAddress;
|
||||
address[] path;
|
||||
IEtherToken weth;
|
||||
}
|
||||
|
||||
/// @dev Bancor ETH pseudo-address.
|
||||
address constant public BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Bancor/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded conversion path addresses and Bancor network address
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
// Decode the bridge data.
|
||||
(
|
||||
state.path,
|
||||
state.bancorNetworkAddress
|
||||
// solhint-disable indent
|
||||
) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
|
||||
require(state.path.length >= 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
|
||||
|
||||
// Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
|
||||
uint256 fromTokenBalance;
|
||||
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 (state.path[0] == BANCOR_ETH_ADDRESS) {
|
||||
fromTokenBalance = state.weth.balanceOf(address(this));
|
||||
state.weth.withdraw(fromTokenBalance);
|
||||
payableAmount = fromTokenBalance;
|
||||
} else {
|
||||
fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
|
||||
}
|
||||
|
||||
// Convert the tokens
|
||||
uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath.value(payableAmount)(
|
||||
state.path, // path originating with source token and terminating in destination token
|
||||
fromTokenBalance, // amount of source token to trade
|
||||
amount, // minimum amount of destination token expected to receive
|
||||
state.path[state.path.length-1] == BANCOR_ETH_ADDRESS ? address(this) : to, // beneficiary
|
||||
address(0), // affiliateAccount; no fee paid
|
||||
0 // affiliateFee; no fee paid
|
||||
);
|
||||
|
||||
if (state.path[state.path.length-1] == BANCOR_ETH_ADDRESS) {
|
||||
state.weth.deposit.value(boughtAmount)();
|
||||
state.weth.transfer(to, boughtAmount);
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
state.path[0] == BANCOR_ETH_ADDRESS ? address(state.weth) : state.path[0],
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IChai.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
contract ChaiBridge is
|
||||
IERC20Bridge,
|
||||
DeploymentConstants
|
||||
{
|
||||
/// @dev Withdraws `amount` of `from` address's Dai from the Chai contract.
|
||||
/// Transfers `amount` of Dai to `to` address.
|
||||
/// @param from Address to transfer asset from.
|
||||
/// @param to Address to transfer asset to.
|
||||
/// @param amount Amount of asset to transfer.
|
||||
/// @return success The magic bytes `0xdc1600f3` if successful.
|
||||
function bridgeTransferFrom(
|
||||
address /* tokenAddress */,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata /* bridgeData */
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Ensure that only the `ERC20BridgeProxy` can call this function.
|
||||
require(
|
||||
msg.sender == _getERC20BridgeProxyAddress(),
|
||||
"ChaiBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY"
|
||||
);
|
||||
|
||||
// Withdraw `from` address's Dai.
|
||||
// NOTE: This contract must be approved to spend Chai on behalf of `from`.
|
||||
bytes memory drawCalldata = abi.encodeWithSelector(
|
||||
IChai(address(0)).draw.selector,
|
||||
from,
|
||||
amount
|
||||
);
|
||||
|
||||
(bool success,) = _getChaiAddress().call(drawCalldata);
|
||||
require(
|
||||
success,
|
||||
"ChaiBridge/DRAW_DAI_FAILED"
|
||||
);
|
||||
|
||||
// Transfer Dai to `to`
|
||||
// This will never fail if the `draw` call was successful
|
||||
IERC20Token(_getDaiAddress()).transfer(to, amount);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IBalancerPool.sol";
|
||||
|
||||
|
||||
contract CreamBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded addresses of the "from" token and Balancer pool.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data.
|
||||
(address fromTokenAddress, address poolAddress) = abi.decode(
|
||||
bridgeData,
|
||||
(address, address)
|
||||
);
|
||||
require(toTokenAddress != fromTokenAddress, "CreamBridge/INVALID_PAIR");
|
||||
|
||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance);
|
||||
|
||||
// Sell all of this contract's `fromTokenAddress` token balance.
|
||||
(uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn(
|
||||
fromTokenAddress, // tokenIn
|
||||
fromTokenBalance, // tokenAmountIn
|
||||
toTokenAddress, // tokenOut
|
||||
amount, // minAmountOut
|
||||
uint256(-1) // maxPrice
|
||||
);
|
||||
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IUniswapV2Router01.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
// solhint-disable not-rely-on-time
|
||||
contract CryptoComBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct TransferState {
|
||||
address[] path;
|
||||
address router;
|
||||
uint256 fromTokenBalance;
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
// solhint-disable indent
|
||||
(state.path, state.router) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
|
||||
require(state.path.length >= 2, "CryptoComBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(state.path[state.path.length - 1] == toTokenAddress, "CryptoComBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (state.path[0] == toTokenAddress) {
|
||||
LibERC20Token.transfer(state.path[0], to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
|
||||
// Grant the SushiSwap router an allowance.
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.path[0],
|
||||
state.router,
|
||||
state.fromTokenBalance
|
||||
);
|
||||
|
||||
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
|
||||
// and transfer it to `to`.
|
||||
IUniswapV2Router01 router = IUniswapV2Router01(state.router);
|
||||
uint[] memory amounts = router.swapExactTokensForTokens(
|
||||
// Sell all tokens we hold.
|
||||
state.fromTokenBalance,
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Convert `fromTokenAddress` to `toTokenAddress`.
|
||||
state.path,
|
||||
// Recipient is `to`.
|
||||
to,
|
||||
// Expires after this block.
|
||||
block.timestamp
|
||||
);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
// input token
|
||||
state.path[0],
|
||||
// output token
|
||||
toTokenAddress,
|
||||
// input token amount
|
||||
state.fromTokenBalance,
|
||||
// output token amount
|
||||
amounts[amounts.length - 1],
|
||||
from,
|
||||
to
|
||||
);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/ICurve.sol";
|
||||
|
||||
|
||||
// solhint-disable not-rely-on-time
|
||||
// solhint-disable space-after-comma
|
||||
contract CurveBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct CurveBridgeData {
|
||||
address curveAddress;
|
||||
bytes4 exchangeFunctionSelector;
|
||||
address fromTokenAddress;
|
||||
int128 fromCoinIdx;
|
||||
int128 toCoinIdx;
|
||||
}
|
||||
|
||||
/// @dev Callback for `ICurve`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
/// (DAI, USDC) to the Curve contract, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoeded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the Curve metadata.
|
||||
CurveBridgeData memory data = abi.decode(bridgeData, (CurveBridgeData));
|
||||
|
||||
require(toTokenAddress != data.fromTokenAddress, "CurveBridge/INVALID_PAIR");
|
||||
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) =
|
||||
data.curveAddress.call(abi.encodeWithSelector(
|
||||
data.exchangeFunctionSelector,
|
||||
data.fromCoinIdx,
|
||||
data.toCoinIdx,
|
||||
// dx
|
||||
fromTokenBalance,
|
||||
// min dy
|
||||
amount
|
||||
));
|
||||
if (!didSucceed) {
|
||||
assembly { revert(add(resultData, 32), mload(resultData)) }
|
||||
}
|
||||
}
|
||||
|
||||
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
data.fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
toTokenBalance,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
interface IDODOHelper {
|
||||
|
||||
function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256);
|
||||
}
|
||||
|
||||
|
||||
interface IDODO {
|
||||
|
||||
function sellBaseToken(uint256 amount, uint256 minReceiveQuote, bytes calldata data) external returns (uint256);
|
||||
|
||||
function buyBaseToken(uint256 amount, uint256 maxPayQuote, bytes calldata data) external returns (uint256);
|
||||
|
||||
}
|
||||
|
||||
|
||||
contract DODOBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
struct TransferState {
|
||||
address fromTokenAddress;
|
||||
uint256 fromTokenBalance;
|
||||
address pool;
|
||||
bool isSellBase;
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
TransferState memory state;
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
(state.fromTokenAddress, state.pool, state.isSellBase) = abi.decode(bridgeData, (address, address, bool));
|
||||
require(state.pool != address(0), "DODOBridge/InvalidPool");
|
||||
IDODO exchange = IDODO(state.pool);
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));
|
||||
|
||||
// Grant the pool an allowance.
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.fromTokenAddress,
|
||||
address(exchange),
|
||||
state.fromTokenBalance
|
||||
);
|
||||
|
||||
uint256 boughtAmount;
|
||||
if (state.isSellBase) {
|
||||
boughtAmount = exchange.sellBaseToken(
|
||||
// amount to sell
|
||||
state.fromTokenBalance,
|
||||
// min receive amount
|
||||
1,
|
||||
new bytes(0)
|
||||
);
|
||||
} else {
|
||||
// Need to re-calculate the sell quote amount into buyBase
|
||||
boughtAmount = IDODOHelper(_getDODOHelperAddress()).querySellQuoteToken(
|
||||
address(exchange),
|
||||
state.fromTokenBalance
|
||||
);
|
||||
exchange.buyBaseToken(
|
||||
// amount to buy
|
||||
boughtAmount,
|
||||
// max pay amount
|
||||
state.fromTokenBalance,
|
||||
new bytes(0)
|
||||
);
|
||||
}
|
||||
// Transfer funds to `to`
|
||||
IERC20Token(toTokenAddress).transfer(to, boughtAmount);
|
||||
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
// input token
|
||||
state.fromTokenAddress,
|
||||
// output token
|
||||
toTokenAddress,
|
||||
// input token amount
|
||||
state.fromTokenBalance,
|
||||
// output token amount
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "./MixinGasToken.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma, indent
|
||||
contract DexForwarderBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants,
|
||||
MixinGasToken
|
||||
{
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Data needed to reconstruct a bridge call.
|
||||
struct BridgeCall {
|
||||
address target;
|
||||
uint256 inputTokenAmount;
|
||||
uint256 outputTokenAmount;
|
||||
bytes bridgeData;
|
||||
}
|
||||
|
||||
/// @dev Intermediate state variables used by `bridgeTransferFrom()`, in
|
||||
/// struct form to get around stack limits.
|
||||
struct TransferFromState {
|
||||
address inputToken;
|
||||
uint256 initialInputTokenBalance;
|
||||
uint256 callInputTokenAmount;
|
||||
uint256 callOutputTokenAmount;
|
||||
uint256 totalInputTokenSold;
|
||||
BridgeCall[] calls;
|
||||
}
|
||||
|
||||
/// @dev Spends this contract's entire balance of input tokens by forwarding
|
||||
/// them to other bridges. Reverts if the entire balance is not spent.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param bridgeData The abi-encoded input token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address outputToken,
|
||||
address /* from */,
|
||||
address to,
|
||||
uint256 /* amount */,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
freesGasTokensFromCollector
|
||||
returns (bytes4 success)
|
||||
{
|
||||
require(
|
||||
msg.sender == _getERC20BridgeProxyAddress(),
|
||||
"DexForwarderBridge/SENDER_NOT_AUTHORIZED"
|
||||
);
|
||||
TransferFromState memory state;
|
||||
(
|
||||
state.inputToken,
|
||||
state.calls
|
||||
) = abi.decode(bridgeData, (address, BridgeCall[]));
|
||||
|
||||
state.initialInputTokenBalance =
|
||||
IERC20Token(state.inputToken).balanceOf(address(this));
|
||||
|
||||
for (uint256 i = 0; i < state.calls.length; ++i) {
|
||||
// Stop if the we've sold all our input tokens.
|
||||
if (state.totalInputTokenSold >= state.initialInputTokenBalance) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Compute token amounts.
|
||||
state.callInputTokenAmount = LibSafeMath.min256(
|
||||
state.calls[i].inputTokenAmount,
|
||||
state.initialInputTokenBalance.safeSub(state.totalInputTokenSold)
|
||||
);
|
||||
state.callOutputTokenAmount = LibMath.getPartialAmountFloor(
|
||||
state.callInputTokenAmount,
|
||||
state.calls[i].inputTokenAmount,
|
||||
state.calls[i].outputTokenAmount
|
||||
);
|
||||
|
||||
// Execute the call in a new context so we can recoup transferred
|
||||
// funds by reverting.
|
||||
(bool didSucceed, ) = address(this)
|
||||
.call(abi.encodeWithSelector(
|
||||
this.executeBridgeCall.selector,
|
||||
state.calls[i].target,
|
||||
to,
|
||||
state.inputToken,
|
||||
outputToken,
|
||||
state.callInputTokenAmount,
|
||||
state.callOutputTokenAmount,
|
||||
state.calls[i].bridgeData
|
||||
));
|
||||
|
||||
if (didSucceed) {
|
||||
// Increase the amount of tokens sold.
|
||||
state.totalInputTokenSold = state.totalInputTokenSold.safeAdd(
|
||||
state.callInputTokenAmount
|
||||
);
|
||||
}
|
||||
}
|
||||
// Always succeed.
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev Transfers `inputToken` token to a bridge contract then calls
|
||||
/// its `bridgeTransferFrom()`. This is executed in separate context
|
||||
/// so we can revert the transfer on error. This can only be called
|
||||
// by this contract itself.
|
||||
/// @param bridge The bridge contract.
|
||||
/// @param to The recipient of `outputToken` tokens.
|
||||
/// @param inputToken The input token.
|
||||
/// @param outputToken The output token.
|
||||
/// @param inputTokenAmount The amount of input tokens to transfer to `bridge`.
|
||||
/// @param outputTokenAmount The amount of expected output tokens to be sent
|
||||
/// to `to` by `bridge`.
|
||||
function executeBridgeCall(
|
||||
address bridge,
|
||||
address to,
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
{
|
||||
// Must be called through `bridgeTransferFrom()`.
|
||||
require(msg.sender == address(this), "DexForwarderBridge/ONLY_SELF");
|
||||
// `bridge` must not be this contract.
|
||||
require(bridge != address(this));
|
||||
|
||||
// Get the starting balance of output tokens for `to`.
|
||||
uint256 initialRecipientBalance = IERC20Token(outputToken).balanceOf(to);
|
||||
|
||||
// Transfer input tokens to the bridge.
|
||||
LibERC20Token.transfer(inputToken, bridge, inputTokenAmount);
|
||||
|
||||
// Call the bridge.
|
||||
(bool didSucceed, bytes memory resultData) =
|
||||
bridge.call(abi.encodeWithSelector(
|
||||
IERC20Bridge(0).bridgeTransferFrom.selector,
|
||||
outputToken,
|
||||
bridge,
|
||||
to,
|
||||
outputTokenAmount,
|
||||
bridgeData
|
||||
));
|
||||
|
||||
// Revert if the call failed or not enough tokens were bought.
|
||||
// This will also undo the token transfer.
|
||||
require(
|
||||
didSucceed
|
||||
&& resultData.length == 32
|
||||
&& LibBytes.readBytes32(resultData, 0) == bytes32(BRIDGE_SUCCESS)
|
||||
&& IERC20Token(outputToken).balanceOf(to).safeSub(initialRecipientBalance) >= outputTokenAmount
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IDydxBridge.sol";
|
||||
import "../interfaces/IDydx.sol";
|
||||
|
||||
|
||||
contract DydxBridge is
|
||||
IERC20Bridge,
|
||||
IDydxBridge,
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
|
||||
/// Notes:
|
||||
/// 1. This bridge must be set as an operator of the input dydx account.
|
||||
/// 2. This function may only be called in the context of the 0x Exchange.
|
||||
/// 3. The maker or taker of the 0x order must be the dydx account owner.
|
||||
/// 4. Deposits into dydx are made from the `from` address.
|
||||
/// 5. Withdrawals from dydx are made to the `to` address.
|
||||
/// 6. Calling this function must always withdraw at least `amount`,
|
||||
/// otherwise the `ERC20Bridge` will revert.
|
||||
/// @param from The sender of the tokens and owner of the dydx account.
|
||||
/// @param to The recipient of the tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to deposit or withdraw.
|
||||
/// @param encodedBridgeData An abi-encoded `BridgeData` struct.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address, /* toTokenAddress */
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata encodedBridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Ensure that only the `ERC20BridgeProxy` can call this function.
|
||||
require(
|
||||
msg.sender == _getERC20BridgeProxyAddress(),
|
||||
"DydxBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY"
|
||||
);
|
||||
|
||||
// Decode bridge data.
|
||||
(BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
|
||||
|
||||
// The dydx accounts are owned by the `from` address.
|
||||
IDydx.AccountInfo[] memory accounts = _createAccounts(from, bridgeData);
|
||||
|
||||
// Create dydx actions to run on the dydx accounts.
|
||||
IDydx.ActionArgs[] memory actions = _createActions(
|
||||
from,
|
||||
to,
|
||||
amount,
|
||||
bridgeData
|
||||
);
|
||||
|
||||
// Run operation. This will revert on failure.
|
||||
IDydx(_getDydxAddress()).operate(accounts, actions);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev Creates an array of accounts for dydx to operate on.
|
||||
/// All accounts must belong to the same owner.
|
||||
/// @param accountOwner Owner of the dydx account.
|
||||
/// @param bridgeData A `BridgeData` struct.
|
||||
function _createAccounts(
|
||||
address accountOwner,
|
||||
BridgeData memory bridgeData
|
||||
)
|
||||
internal
|
||||
returns (IDydx.AccountInfo[] memory accounts)
|
||||
{
|
||||
uint256[] memory accountNumbers = bridgeData.accountNumbers;
|
||||
uint256 nAccounts = accountNumbers.length;
|
||||
accounts = new IDydx.AccountInfo[](nAccounts);
|
||||
for (uint256 i = 0; i < nAccounts; ++i) {
|
||||
accounts[i] = IDydx.AccountInfo({
|
||||
owner: accountOwner,
|
||||
number: accountNumbers[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Creates an array of actions to carry out on dydx.
|
||||
/// @param depositFrom Deposit value from this address (owner of the dydx account).
|
||||
/// @param withdrawTo Withdraw value to this address.
|
||||
/// @param amount The amount of value available to operate on.
|
||||
/// @param bridgeData A `BridgeData` struct.
|
||||
function _createActions(
|
||||
address depositFrom,
|
||||
address withdrawTo,
|
||||
uint256 amount,
|
||||
BridgeData memory bridgeData
|
||||
)
|
||||
internal
|
||||
returns (IDydx.ActionArgs[] memory actions)
|
||||
{
|
||||
BridgeAction[] memory bridgeActions = bridgeData.actions;
|
||||
uint256 nBridgeActions = bridgeActions.length;
|
||||
actions = new IDydx.ActionArgs[](nBridgeActions);
|
||||
for (uint256 i = 0; i < nBridgeActions; ++i) {
|
||||
// Cache current bridge action.
|
||||
BridgeAction memory bridgeAction = bridgeActions[i];
|
||||
|
||||
// Scale amount, if conversion rate is set.
|
||||
uint256 scaledAmount;
|
||||
if (bridgeAction.conversionRateDenominator > 0) {
|
||||
scaledAmount = LibMath.safeGetPartialAmountFloor(
|
||||
bridgeAction.conversionRateNumerator,
|
||||
bridgeAction.conversionRateDenominator,
|
||||
amount
|
||||
);
|
||||
} else {
|
||||
scaledAmount = amount;
|
||||
}
|
||||
|
||||
// Construct dydx action.
|
||||
if (bridgeAction.actionType == BridgeActionType.Deposit) {
|
||||
// Deposit tokens from the account owner into their dydx account.
|
||||
actions[i] = _createDepositAction(
|
||||
depositFrom,
|
||||
scaledAmount,
|
||||
bridgeAction
|
||||
);
|
||||
} else if (bridgeAction.actionType == BridgeActionType.Withdraw) {
|
||||
// Withdraw tokens from dydx to the `otherAccount`.
|
||||
actions[i] = _createWithdrawAction(
|
||||
withdrawTo,
|
||||
scaledAmount,
|
||||
bridgeAction
|
||||
);
|
||||
} else {
|
||||
// If all values in the `Action` enum are handled then this
|
||||
// revert is unreachable: Solidity will revert when casting
|
||||
// from `uint8` to `Action`.
|
||||
revert("DydxBridge/UNRECOGNIZED_BRIDGE_ACTION");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Returns a dydx `DepositAction`.
|
||||
/// @param depositFrom Deposit tokens from this address who is also the account owner.
|
||||
/// @param amount of tokens to deposit.
|
||||
/// @param bridgeAction A `BridgeAction` struct.
|
||||
/// @return depositAction The encoded dydx action.
|
||||
function _createDepositAction(
|
||||
address depositFrom,
|
||||
uint256 amount,
|
||||
BridgeAction memory bridgeAction
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
IDydx.ActionArgs memory depositAction
|
||||
)
|
||||
{
|
||||
// Create dydx amount.
|
||||
IDydx.AssetAmount memory dydxAmount = IDydx.AssetAmount({
|
||||
sign: true, // true if positive.
|
||||
denomination: IDydx.AssetDenomination.Wei, // Wei => actual token amount held in account.
|
||||
ref: IDydx.AssetReference.Delta, // Delta => a relative amount.
|
||||
value: amount // amount to deposit.
|
||||
});
|
||||
|
||||
// Create dydx deposit action.
|
||||
depositAction = IDydx.ActionArgs({
|
||||
actionType: IDydx.ActionType.Deposit, // deposit tokens.
|
||||
amount: dydxAmount, // amount to deposit.
|
||||
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
|
||||
primaryMarketId: bridgeAction.marketId, // indicates which token to deposit.
|
||||
otherAddress: depositFrom, // deposit from the account owner.
|
||||
// unused parameters
|
||||
secondaryMarketId: 0,
|
||||
otherAccountIdx: 0,
|
||||
data: hex''
|
||||
});
|
||||
}
|
||||
|
||||
/// @dev Returns a dydx `WithdrawAction`.
|
||||
/// @param withdrawTo Withdraw tokens to this address.
|
||||
/// @param amount of tokens to withdraw.
|
||||
/// @param bridgeAction A `BridgeAction` struct.
|
||||
/// @return withdrawAction The encoded dydx action.
|
||||
function _createWithdrawAction(
|
||||
address withdrawTo,
|
||||
uint256 amount,
|
||||
BridgeAction memory bridgeAction
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (
|
||||
IDydx.ActionArgs memory withdrawAction
|
||||
)
|
||||
{
|
||||
// Create dydx amount.
|
||||
IDydx.AssetAmount memory amountToWithdraw = IDydx.AssetAmount({
|
||||
sign: false, // false if negative.
|
||||
denomination: IDydx.AssetDenomination.Wei, // Wei => actual token amount held in account.
|
||||
ref: IDydx.AssetReference.Delta, // Delta => a relative amount.
|
||||
value: amount // amount to withdraw.
|
||||
});
|
||||
|
||||
// Create withdraw action.
|
||||
withdrawAction = IDydx.ActionArgs({
|
||||
actionType: IDydx.ActionType.Withdraw, // withdraw tokens.
|
||||
amount: amountToWithdraw, // amount to withdraw.
|
||||
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
|
||||
primaryMarketId: bridgeAction.marketId, // indicates which token to withdraw.
|
||||
otherAddress: withdrawTo, // withdraw tokens to this address.
|
||||
// unused parameters
|
||||
secondaryMarketId: 0,
|
||||
otherAccountIdx: 0,
|
||||
data: hex''
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IEth2Dai.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
contract Eth2DaiBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
/// (DAI or WETH) to the Eth2Dai contract, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to give to `to` (either DAI or WETH).
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoeded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
(address fromTokenAddress) = abi.decode(bridgeData, (address));
|
||||
|
||||
IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress());
|
||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
uint256 boughtAmount = exchange.sellAllAmount(
|
||||
fromTokenAddress,
|
||||
fromTokenBalance,
|
||||
toTokenAddress,
|
||||
amount
|
||||
);
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IKyberNetworkProxy.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
contract KyberBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
// @dev Structure used internally to get around stack limits.
|
||||
struct TradeState {
|
||||
IKyberNetworkProxy kyber;
|
||||
IEtherToken weth;
|
||||
address fromTokenAddress;
|
||||
uint256 fromTokenBalance;
|
||||
uint256 payableAmount;
|
||||
uint256 conversionRate;
|
||||
bytes hint;
|
||||
}
|
||||
|
||||
/// @dev Kyber ETH pseudo-address.
|
||||
address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
/// @dev `bridgeTransferFrom()` failure result.
|
||||
bytes4 constant private BRIDGE_FAILED = 0x0;
|
||||
/// @dev Precision of Kyber rates.
|
||||
uint256 constant private KYBER_RATE_BASE = 10 ** 18;
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from Kyber/WETH.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{
|
||||
// Poor man's receive in 0.5.9
|
||||
require(msg.data.length == 0);
|
||||
}
|
||||
|
||||
/// @dev Callback for `IKyberBridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
/// to the `KyberNetworkProxy` contract, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to give to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoeded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
TradeState memory state;
|
||||
state.kyber = IKyberNetworkProxy(_getKyberNetworkProxyAddress());
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
(state.fromTokenAddress, state.hint) = abi.decode(bridgeData, (address, bytes));
|
||||
// Query the balance of "from" tokens.
|
||||
state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));
|
||||
if (state.fromTokenBalance == 0) {
|
||||
// Return failure if no input tokens.
|
||||
return BRIDGE_FAILED;
|
||||
}
|
||||
if (state.fromTokenAddress == toTokenAddress) {
|
||||
// Just transfer the tokens if they're the same.
|
||||
LibERC20Token.transfer(state.fromTokenAddress, to, state.fromTokenBalance);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
if (state.fromTokenAddress == address(state.weth)) {
|
||||
// From WETH
|
||||
state.fromTokenAddress = KYBER_ETH_ADDRESS;
|
||||
state.payableAmount = state.fromTokenBalance;
|
||||
state.weth.withdraw(state.fromTokenBalance);
|
||||
} else {
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.fromTokenAddress,
|
||||
address(state.kyber),
|
||||
state.fromTokenBalance
|
||||
);
|
||||
}
|
||||
bool isToTokenWeth = toTokenAddress == address(state.weth);
|
||||
|
||||
// Try to sell all of this contract's input token balance through
|
||||
// `KyberNetworkProxy.trade()`.
|
||||
uint256 boughtAmount = state.kyber.tradeWithHint.value(state.payableAmount)(
|
||||
// Input token.
|
||||
state.fromTokenAddress,
|
||||
// Sell amount.
|
||||
state.fromTokenBalance,
|
||||
// Output token.
|
||||
isToTokenWeth ? KYBER_ETH_ADDRESS : toTokenAddress,
|
||||
// Transfer to this contract if converting to ETH, otherwise
|
||||
// transfer directly to the recipient.
|
||||
isToTokenWeth ? address(uint160(address(this))) : address(uint160(to)),
|
||||
// Buy as much as possible.
|
||||
uint256(-1),
|
||||
// The minimum conversion rate
|
||||
1,
|
||||
// No affiliate address.
|
||||
address(0),
|
||||
state.hint
|
||||
);
|
||||
// Wrap ETH output and transfer to recipient.
|
||||
if (isToTokenWeth) {
|
||||
state.weth.deposit.value(boughtAmount)();
|
||||
state.weth.transfer(to, boughtAmount);
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
state.fromTokenAddress == KYBER_ETH_ADDRESS ? address(state.weth) : state.fromTokenAddress,
|
||||
toTokenAddress,
|
||||
state.fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IMStable.sol";
|
||||
|
||||
|
||||
contract MStableBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
/// @dev Swaps specified tokens against the mStable mUSD contract
|
||||
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
// solhint-disable no-unused-vars
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
(address fromTokenAddress) = abi.decode(bridgeData, (address));
|
||||
|
||||
IMStable exchange = IMStable(_getMUsdAddress());
|
||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
uint256 boughtAmount = exchange.swap(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
to
|
||||
);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.16;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IGasToken.sol";
|
||||
|
||||
|
||||
contract MixinGasToken is
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
/// @dev Frees gas tokens based on the amount of gas consumed in the function
|
||||
modifier freesGasTokens {
|
||||
uint256 gasBefore = gasleft();
|
||||
_;
|
||||
IGasToken gst = IGasToken(_getGstAddress());
|
||||
if (address(gst) != address(0)) {
|
||||
// (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
|
||||
// 14154 24000 6870
|
||||
uint256 value = (gasBefore - gasleft() + 14154) / 41130;
|
||||
gst.freeUpTo(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Frees gas tokens using the balance of `from`. Amount freed is based
|
||||
/// on the gas consumed in the function
|
||||
modifier freesGasTokensFromCollector() {
|
||||
uint256 gasBefore = gasleft();
|
||||
_;
|
||||
IGasToken gst = IGasToken(_getGstAddress());
|
||||
if (address(gst) != address(0)) {
|
||||
// (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
|
||||
// 14154 24000 6870
|
||||
uint256 value = (gasBefore - gasleft() + 14154) / 41130;
|
||||
gst.freeFromUpTo(_getGstCollectorAddress(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IMooniswap.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
// solhint-disable not-rely-on-time
|
||||
contract MooniswapBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
struct TransferState {
|
||||
IMooniswap pool;
|
||||
uint256 fromTokenBalance;
|
||||
IEtherToken weth;
|
||||
uint256 boughtAmount;
|
||||
address fromTokenAddress;
|
||||
address toTokenAddress;
|
||||
}
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from uniswap.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// State memory object to avoid stack overflows.
|
||||
TransferState memory state;
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
address fromTokenAddress = abi.decode(bridgeData, (address));
|
||||
// Get the weth contract.
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
|
||||
state.fromTokenAddress = fromTokenAddress == address(state.weth) ? address(0) : fromTokenAddress;
|
||||
state.toTokenAddress = toTokenAddress == address(state.weth) ? address(0) : toTokenAddress;
|
||||
state.pool = IMooniswap(
|
||||
IMooniswapRegistry(_getMooniswapAddress()).pools(
|
||||
state.fromTokenAddress,
|
||||
state.toTokenAddress
|
||||
)
|
||||
);
|
||||
|
||||
// withdraw WETH to ETH
|
||||
if (state.fromTokenAddress == address(0)) {
|
||||
state.weth.withdraw(state.fromTokenBalance);
|
||||
} else {
|
||||
// Grant the pool an allowance.
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.fromTokenAddress,
|
||||
address(state.pool),
|
||||
state.fromTokenBalance
|
||||
);
|
||||
}
|
||||
uint256 ethValue = state.fromTokenAddress == address(0) ? state.fromTokenBalance : 0;
|
||||
state.boughtAmount = state.pool.swap.value(ethValue)(
|
||||
state.fromTokenAddress,
|
||||
state.toTokenAddress,
|
||||
state.fromTokenBalance,
|
||||
amount,
|
||||
address(0)
|
||||
);
|
||||
// Deposit to WETH
|
||||
if (state.toTokenAddress == address(0)) {
|
||||
state.weth.deposit.value(state.boughtAmount)();
|
||||
}
|
||||
|
||||
// Transfer funds to `to`
|
||||
LibERC20Token.transfer(toTokenAddress, to, state.boughtAmount);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
// input token
|
||||
fromTokenAddress,
|
||||
// output token
|
||||
toTokenAddress,
|
||||
// input token amount
|
||||
state.fromTokenBalance,
|
||||
// output token amount
|
||||
state.boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/IShell.sol";
|
||||
|
||||
|
||||
contract ShellBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
|
||||
/// @dev Swaps specified tokens against the Shell contract
|
||||
/// @param toTokenAddress The token to give to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
// solhint-disable no-unused-vars
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the `fromTokenAddress` and `pool`.
|
||||
(address fromTokenAddress, address pool) = abi.decode(bridgeData, (address, address));
|
||||
|
||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(fromTokenAddress, pool, fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
uint256 boughtAmount = IShell(pool).originSwap(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
amount, // min amount
|
||||
block.timestamp + 1
|
||||
);
|
||||
LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/ICurve.sol";
|
||||
|
||||
|
||||
// solhint-disable not-rely-on-time
|
||||
// solhint-disable space-after-comma
|
||||
contract SnowSwapBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct SnowSwapBridgeData {
|
||||
address curveAddress;
|
||||
bytes4 exchangeFunctionSelector;
|
||||
address fromTokenAddress;
|
||||
int128 fromCoinIdx;
|
||||
int128 toCoinIdx;
|
||||
}
|
||||
|
||||
/// @dev Callback for `ICurve`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
/// (DAI, USDC) to the Curve contract, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoeded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the SnowSwap metadata.
|
||||
SnowSwapBridgeData memory data = abi.decode(bridgeData, (SnowSwapBridgeData));
|
||||
|
||||
require(toTokenAddress != data.fromTokenAddress, "SnowSwapBridge/INVALID_PAIR");
|
||||
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) =
|
||||
data.curveAddress.call(abi.encodeWithSelector(
|
||||
data.exchangeFunctionSelector,
|
||||
data.fromCoinIdx,
|
||||
data.toCoinIdx,
|
||||
// dx
|
||||
fromTokenBalance,
|
||||
// min dy
|
||||
amount
|
||||
));
|
||||
if (!didSucceed) {
|
||||
assembly { revert(add(resultData, 32), mload(resultData)) }
|
||||
}
|
||||
}
|
||||
|
||||
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
data.fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
toTokenBalance,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IUniswapV2Router01.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
// solhint-disable not-rely-on-time
|
||||
contract SushiSwapBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct TransferState {
|
||||
address[] path;
|
||||
address router;
|
||||
uint256 fromTokenBalance;
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
// solhint-disable indent
|
||||
(state.path, state.router) = abi.decode(bridgeData, (address[], address));
|
||||
// solhint-enable indent
|
||||
|
||||
require(state.path.length >= 2, "SushiSwapBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(state.path[state.path.length - 1] == toTokenAddress, "SushiSwapBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (state.path[0] == toTokenAddress) {
|
||||
LibERC20Token.transfer(state.path[0], to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
|
||||
// Grant the SushiSwap router an allowance.
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.path[0],
|
||||
state.router,
|
||||
state.fromTokenBalance
|
||||
);
|
||||
|
||||
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
|
||||
// and transfer it to `to`.
|
||||
IUniswapV2Router01 router = IUniswapV2Router01(state.router);
|
||||
uint[] memory amounts = router.swapExactTokensForTokens(
|
||||
// Sell all tokens we hold.
|
||||
state.fromTokenBalance,
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Convert `fromTokenAddress` to `toTokenAddress`.
|
||||
state.path,
|
||||
// Recipient is `to`.
|
||||
to,
|
||||
// Expires after this block.
|
||||
block.timestamp
|
||||
);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
// input token
|
||||
state.path[0],
|
||||
// output token
|
||||
toTokenAddress,
|
||||
// input token amount
|
||||
state.fromTokenBalance,
|
||||
// output token amount
|
||||
amounts[amounts.length - 1],
|
||||
from,
|
||||
to
|
||||
);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
import "../interfaces/ICurve.sol";
|
||||
|
||||
|
||||
// solhint-disable not-rely-on-time
|
||||
// solhint-disable space-after-comma
|
||||
contract SwerveBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct SwerveBridgeData {
|
||||
address curveAddress;
|
||||
bytes4 exchangeFunctionSelector;
|
||||
address fromTokenAddress;
|
||||
int128 fromCoinIdx;
|
||||
int128 toCoinIdx;
|
||||
}
|
||||
|
||||
/// @dev Callback for `ICurve`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
|
||||
/// (DAI, USDC) to the Curve contract, then transfers the bought
|
||||
/// tokens to `to`.
|
||||
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoeded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// Decode the bridge data to get the SwerveBridgeData metadata.
|
||||
SwerveBridgeData memory data = abi.decode(bridgeData, (SwerveBridgeData));
|
||||
|
||||
require(toTokenAddress != data.fromTokenAddress, "SwerveBridge/INVALID_PAIR");
|
||||
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
|
||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
|
||||
|
||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) =
|
||||
data.curveAddress.call(abi.encodeWithSelector(
|
||||
data.exchangeFunctionSelector,
|
||||
data.fromCoinIdx,
|
||||
data.toCoinIdx,
|
||||
// dx
|
||||
fromTokenBalance,
|
||||
// min dy
|
||||
amount
|
||||
));
|
||||
if (!didSucceed) {
|
||||
assembly { revert(add(resultData, 32), mload(resultData)) }
|
||||
}
|
||||
}
|
||||
|
||||
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
|
||||
// Transfer the converted `toToken`s to `to`.
|
||||
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
data.fromTokenAddress,
|
||||
toTokenAddress,
|
||||
fromTokenBalance,
|
||||
toTokenBalance,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Magic success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IUniswapExchangeFactory.sol";
|
||||
import "../interfaces/IUniswapExchange.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
// solhint-disable not-rely-on-time
|
||||
contract UniswapBridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
// Struct to hold `bridgeTransferFrom()` local variables in memory and to avoid
|
||||
// stack overflows.
|
||||
struct TransferState {
|
||||
IUniswapExchange exchange;
|
||||
uint256 fromTokenBalance;
|
||||
IEtherToken weth;
|
||||
uint256 boughtAmount;
|
||||
}
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
/// @dev Payable fallback to receive ETH from uniswap.
|
||||
function ()
|
||||
external
|
||||
payable
|
||||
{}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded "from" token address.
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// State memory object to avoid stack overflows.
|
||||
TransferState memory state;
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
(address fromTokenAddress) = abi.decode(bridgeData, (address));
|
||||
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (fromTokenAddress == toTokenAddress) {
|
||||
LibERC20Token.transfer(fromTokenAddress, to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
// Get the exchange for the token pair.
|
||||
state.exchange = _getUniswapExchangeForTokenPair(
|
||||
fromTokenAddress,
|
||||
toTokenAddress
|
||||
);
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||
// Get the weth contract.
|
||||
state.weth = IEtherToken(_getWethAddress());
|
||||
|
||||
// Convert from WETH to a token.
|
||||
if (fromTokenAddress == address(state.weth)) {
|
||||
// Unwrap the WETH.
|
||||
state.weth.withdraw(state.fromTokenBalance);
|
||||
// Buy as much of `toTokenAddress` token with ETH as possible and
|
||||
// transfer it to `to`.
|
||||
state.boughtAmount = state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)(
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Expires after this block.
|
||||
block.timestamp,
|
||||
// Recipient is `to`.
|
||||
to
|
||||
);
|
||||
|
||||
// Convert from a token to WETH.
|
||||
} else if (toTokenAddress == address(state.weth)) {
|
||||
// Grant the exchange an allowance.
|
||||
_grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
|
||||
// Buy as much ETH with `fromTokenAddress` token as possible.
|
||||
state.boughtAmount = state.exchange.tokenToEthSwapInput(
|
||||
// Sell all tokens we hold.
|
||||
state.fromTokenBalance,
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Expires after this block.
|
||||
block.timestamp
|
||||
);
|
||||
// Wrap the ETH.
|
||||
state.weth.deposit.value(state.boughtAmount)();
|
||||
// Transfer the WETH to `to`.
|
||||
IEtherToken(toTokenAddress).transfer(to, state.boughtAmount);
|
||||
|
||||
// Convert from one token to another.
|
||||
} else {
|
||||
// Grant the exchange an allowance.
|
||||
_grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
|
||||
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
|
||||
// and transfer it to `to`.
|
||||
state.boughtAmount = state.exchange.tokenToTokenTransferInput(
|
||||
// Sell all tokens we hold.
|
||||
state.fromTokenBalance,
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Must buy at least 1 intermediate ETH.
|
||||
1,
|
||||
// Expires after this block.
|
||||
block.timestamp,
|
||||
// Recipient is `to`.
|
||||
to,
|
||||
// Convert to `toTokenAddress`.
|
||||
toTokenAddress
|
||||
);
|
||||
}
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
fromTokenAddress,
|
||||
toTokenAddress,
|
||||
state.fromTokenBalance,
|
||||
state.boughtAmount,
|
||||
from,
|
||||
to
|
||||
);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
/// @dev Grants an unlimited allowance to the exchange for its token
|
||||
/// on behalf of this contract.
|
||||
/// @param exchange The Uniswap token exchange.
|
||||
/// @param tokenAddress The token address for the exchange.
|
||||
/// @param minimumAllowance The minimum necessary allowance.
|
||||
function _grantExchangeAllowance(
|
||||
IUniswapExchange exchange,
|
||||
address tokenAddress,
|
||||
uint256 minimumAllowance
|
||||
)
|
||||
private
|
||||
{
|
||||
LibERC20Token.approveIfBelow(
|
||||
tokenAddress,
|
||||
address(exchange),
|
||||
minimumAllowance
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Retrieves the uniswap exchange for a given token pair.
|
||||
/// In the case of a WETH-token exchange, this will be the non-WETH token.
|
||||
/// In th ecase of a token-token exchange, this will be the first token.
|
||||
/// @param fromTokenAddress The address of the token we are converting from.
|
||||
/// @param toTokenAddress The address of the token we are converting to.
|
||||
/// @return exchange The uniswap exchange.
|
||||
function _getUniswapExchangeForTokenPair(
|
||||
address fromTokenAddress,
|
||||
address toTokenAddress
|
||||
)
|
||||
private
|
||||
view
|
||||
returns (IUniswapExchange exchange)
|
||||
{
|
||||
address exchangeTokenAddress = fromTokenAddress;
|
||||
// Whichever isn't WETH is the exchange token.
|
||||
if (fromTokenAddress == _getWethAddress()) {
|
||||
exchangeTokenAddress = toTokenAddress;
|
||||
}
|
||||
exchange = IUniswapExchange(
|
||||
IUniswapExchangeFactory(_getUniswapExchangeFactoryAddress())
|
||||
.getExchange(exchangeTokenAddress)
|
||||
);
|
||||
require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN");
|
||||
return exchange;
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "../interfaces/IUniswapV2Router01.sol";
|
||||
import "../interfaces/IERC20Bridge.sol";
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
// solhint-disable not-rely-on-time
|
||||
contract UniswapV2Bridge is
|
||||
IERC20Bridge,
|
||||
IWallet,
|
||||
DeploymentConstants
|
||||
{
|
||||
struct TransferState {
|
||||
address[] path;
|
||||
uint256 fromTokenBalance;
|
||||
}
|
||||
|
||||
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||
/// token encoded in the bridge data.
|
||||
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||
/// @param from The maker (this contract).
|
||||
/// @param to The recipient of the bought tokens.
|
||||
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||
/// @return success The magic bytes if successful.
|
||||
function bridgeTransferFrom(
|
||||
address toTokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
// hold variables to get around stack depth limitations
|
||||
TransferState memory state;
|
||||
|
||||
// Decode the bridge data to get the `fromTokenAddress`.
|
||||
// solhint-disable indent
|
||||
state.path = abi.decode(bridgeData, (address[]));
|
||||
// solhint-enable indent
|
||||
|
||||
require(state.path.length >= 2, "UniswapV2Bridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||
require(state.path[state.path.length - 1] == toTokenAddress, "UniswapV2Bridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||
|
||||
// Just transfer the tokens if they're the same.
|
||||
if (state.path[0] == toTokenAddress) {
|
||||
LibERC20Token.transfer(state.path[0], to, amount);
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
// Get our balance of `fromTokenAddress` token.
|
||||
state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||
|
||||
// Grant the Uniswap router an allowance.
|
||||
LibERC20Token.approveIfBelow(
|
||||
state.path[0],
|
||||
_getUniswapV2Router01Address(),
|
||||
state.fromTokenBalance
|
||||
);
|
||||
|
||||
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
|
||||
// and transfer it to `to`.
|
||||
IUniswapV2Router01 router = IUniswapV2Router01(_getUniswapV2Router01Address());
|
||||
uint[] memory amounts = router.swapExactTokensForTokens(
|
||||
// Sell all tokens we hold.
|
||||
state.fromTokenBalance,
|
||||
// Minimum buy amount.
|
||||
amount,
|
||||
// Convert `fromTokenAddress` to `toTokenAddress`.
|
||||
state.path,
|
||||
// Recipient is `to`.
|
||||
to,
|
||||
// Expires after this block.
|
||||
block.timestamp
|
||||
);
|
||||
|
||||
emit ERC20BridgeTransfer(
|
||||
// input token
|
||||
state.path[0],
|
||||
// output token
|
||||
toTokenAddress,
|
||||
// input token amount
|
||||
state.fromTokenBalance,
|
||||
// output token amount
|
||||
amounts[amounts.length - 1],
|
||||
from,
|
||||
to
|
||||
);
|
||||
|
||||
return BRIDGE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||
/// and sign for itself in orders. Always succeeds.
|
||||
/// @return magicValue Success bytes, always.
|
||||
function isValidSignature(
|
||||
bytes32,
|
||||
bytes calldata
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bytes4 magicValue)
|
||||
{
|
||||
return LEGACY_WALLET_MAGIC_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
// solhint-disable
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
// @dev Interface of the asset proxy's assetData.
|
||||
// The asset proxies take an ABI encoded `bytes assetData` as argument.
|
||||
// This argument is ABI encoded as one of the methods of this interface.
|
||||
interface IAssetData {
|
||||
|
||||
/// @dev Function signature for encoding ERC20 assetData.
|
||||
/// @param tokenAddress Address of ERC20Token contract.
|
||||
function ERC20Token(address tokenAddress)
|
||||
external;
|
||||
|
||||
/// @dev Function signature for encoding ERC721 assetData.
|
||||
/// @param tokenAddress Address of ERC721 token contract.
|
||||
/// @param tokenId Id of ERC721 token to be transferred.
|
||||
function ERC721Token(
|
||||
address tokenAddress,
|
||||
uint256 tokenId
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Function signature for encoding ERC1155 assetData.
|
||||
/// @param tokenAddress Address of ERC1155 token contract.
|
||||
/// @param tokenIds Array of ids of tokens to be transferred.
|
||||
/// @param values Array of values that correspond to each token id to be transferred.
|
||||
/// Note that each value will be multiplied by the amount being filled in the order before transferring.
|
||||
/// @param callbackData Extra data to be passed to receiver's `onERC1155Received` callback function.
|
||||
function ERC1155Assets(
|
||||
address tokenAddress,
|
||||
uint256[] calldata tokenIds,
|
||||
uint256[] calldata values,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Function signature for encoding MultiAsset assetData.
|
||||
/// @param values Array of amounts that correspond to each asset to be transferred.
|
||||
/// Note that each value will be multiplied by the amount being filled in the order before transferring.
|
||||
/// @param nestedAssetData Array of assetData fields that will be be dispatched to their correspnding AssetProxy contract.
|
||||
function MultiAsset(
|
||||
uint256[] calldata values,
|
||||
bytes[] calldata nestedAssetData
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Function signature for encoding StaticCall assetData.
|
||||
/// @param staticCallTargetAddress Address that will execute the staticcall.
|
||||
/// @param staticCallData Data that will be executed via staticcall on the staticCallTargetAddress.
|
||||
/// @param expectedReturnDataHash Keccak-256 hash of the expected staticcall return data.
|
||||
function StaticCall(
|
||||
address staticCallTargetAddress,
|
||||
bytes calldata staticCallData,
|
||||
bytes32 expectedReturnDataHash
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Function signature for encoding ERC20Bridge assetData.
|
||||
/// @param tokenAddress Address of token to transfer.
|
||||
/// @param bridgeAddress Address of the bridge contract.
|
||||
/// @param bridgeData Arbitrary data to be passed to the bridge contract.
|
||||
function ERC20Bridge(
|
||||
address tokenAddress,
|
||||
address bridgeAddress,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
contract IAssetProxy {
|
||||
|
||||
/// @dev Transfers assets. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param from Address to transfer asset from.
|
||||
/// @param to Address to transfer asset to.
|
||||
/// @param amount Amount of asset to transfer.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
contract IAssetProxyDispatcher {
|
||||
|
||||
// Logs registration of new asset proxy
|
||||
event AssetProxyRegistered(
|
||||
bytes4 id, // Id of new registered AssetProxy.
|
||||
address assetProxy // Address of new registered AssetProxy.
|
||||
);
|
||||
|
||||
/// @dev Registers an asset proxy to its asset proxy id.
|
||||
/// Once an asset proxy is registered, it cannot be unregistered.
|
||||
/// @param assetProxy Address of new asset proxy to register.
|
||||
function registerAssetProxy(address assetProxy)
|
||||
external;
|
||||
|
||||
/// @dev Gets an asset proxy.
|
||||
/// @param assetProxyId Id of the asset proxy.
|
||||
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
|
||||
function getAssetProxy(bytes4 assetProxyId)
|
||||
external
|
||||
view
|
||||
returns (address);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol";
|
||||
|
||||
|
||||
contract IAuthorizable is
|
||||
IOwnable
|
||||
{
|
||||
// Event logged when a new address is authorized.
|
||||
event AuthorizedAddressAdded(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
// Event logged when a currently authorized address is unauthorized.
|
||||
event AuthorizedAddressRemoved(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
external
|
||||
view
|
||||
returns (address[] memory);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
interface IBalancerPool {
|
||||
/// @dev Sell `tokenAmountIn` of `tokenIn` and receive `tokenOut`.
|
||||
/// @param tokenIn The token being sold
|
||||
/// @param tokenAmountIn The amount of `tokenIn` to sell.
|
||||
/// @param tokenOut The token being bought.
|
||||
/// @param minAmountOut The minimum amount of `tokenOut` to buy.
|
||||
/// @param maxPrice The maximum value for `spotPriceAfter`.
|
||||
/// @return tokenAmountOut The amount of `tokenOut` bought.
|
||||
/// @return spotPriceAfter The new marginal spot price of the given
|
||||
/// token pair for this pool.
|
||||
function swapExactAmountIn(
|
||||
address tokenIn,
|
||||
uint tokenAmountIn,
|
||||
address tokenOut,
|
||||
uint minAmountOut,
|
||||
uint maxPrice
|
||||
) external returns (uint tokenAmountOut, uint spotPriceAfter);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract IContractRegistry {
|
||||
function addressOf(
|
||||
bytes32 contractName
|
||||
) external returns(address);
|
||||
}
|
||||
|
||||
|
||||
contract IBancorNetwork {
|
||||
function convertByPath(
|
||||
address[] calldata _path,
|
||||
uint256 _amount,
|
||||
uint256 _minReturn,
|
||||
address _beneficiary,
|
||||
address _affiliateAccount,
|
||||
uint256 _affiliateFee
|
||||
) external payable returns (uint256);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
|
||||
|
||||
contract PotLike {
|
||||
function chi() external returns (uint256);
|
||||
function rho() external returns (uint256);
|
||||
function drip() external returns (uint256);
|
||||
function join(uint256) external;
|
||||
function exit(uint256) external;
|
||||
}
|
||||
|
||||
|
||||
// The actual Chai contract can be found here: https://github.com/dapphub/chai
|
||||
contract IChai is
|
||||
IERC20Token
|
||||
{
|
||||
/// @dev Withdraws Dai owned by `src`
|
||||
/// @param src Address that owns Dai.
|
||||
/// @param wad Amount of Dai to withdraw.
|
||||
function draw(
|
||||
address src,
|
||||
uint256 wad
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Queries Dai balance of Chai holder.
|
||||
/// @param usr Address of Chai holder.
|
||||
/// @return Dai balance.
|
||||
function dai(address usr)
|
||||
external
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Queries the Pot contract used by the Chai contract.
|
||||
function pot()
|
||||
external
|
||||
returns (PotLike);
|
||||
|
||||
/// @dev Deposits Dai in exchange for Chai
|
||||
/// @param dst Address to receive Chai.
|
||||
/// @param wad Amount of Dai to deposit.
|
||||
function join(
|
||||
address dst,
|
||||
uint256 wad
|
||||
)
|
||||
external;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
interface ICurve {
|
||||
|
||||
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||
/// This function exists on later versions of Curve (USDC/DAI/USDT)
|
||||
/// @param i The token index being sold.
|
||||
/// @param j The token index being bought.
|
||||
/// @param sellAmount The amount of token being bought.
|
||||
/// @param minBuyAmount The minimum buy amount of the token being bought.
|
||||
function exchange_underlying(
|
||||
int128 i,
|
||||
int128 j,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
|
||||
/// @param i The token index being sold.
|
||||
/// @param j The token index being bought.
|
||||
/// @param sellAmount The amount of token being bought.
|
||||
function get_dy_underlying(
|
||||
int128 i,
|
||||
int128 j,
|
||||
uint256 sellAmount
|
||||
)
|
||||
external
|
||||
returns (uint256 dy);
|
||||
|
||||
/// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
|
||||
/// @param i The token index being sold.
|
||||
/// @param j The token index being bought.
|
||||
/// @param buyAmount The amount of token being bought.
|
||||
function get_dx_underlying(
|
||||
int128 i,
|
||||
int128 j,
|
||||
uint256 buyAmount
|
||||
)
|
||||
external
|
||||
returns (uint256 dx);
|
||||
|
||||
/// @dev Get the underlying token address from the token index
|
||||
/// @param i The token index.
|
||||
function underlying_coins(
|
||||
int128 i
|
||||
)
|
||||
external
|
||||
returns (address tokenAddress);
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
interface IDydx {
|
||||
|
||||
/// @dev Represents the unique key that specifies an account
|
||||
struct AccountInfo {
|
||||
address owner; // The address that owns the account
|
||||
uint256 number; // A nonce that allows a single address to control many accounts
|
||||
}
|
||||
|
||||
enum ActionType {
|
||||
Deposit, // supply tokens
|
||||
Withdraw, // borrow tokens
|
||||
Transfer, // transfer balance between accounts
|
||||
Buy, // buy an amount of some token (externally)
|
||||
Sell, // sell an amount of some token (externally)
|
||||
Trade, // trade tokens against another account
|
||||
Liquidate, // liquidate an undercollateralized or expiring account
|
||||
Vaporize, // use excess tokens to zero-out a completely negative account
|
||||
Call // send arbitrary data to an address
|
||||
}
|
||||
|
||||
/// @dev Arguments that are passed to Solo in an ordered list as part of a single operation.
|
||||
/// Each ActionArgs has an actionType which specifies which action struct that this data will be
|
||||
/// parsed into before being processed.
|
||||
struct ActionArgs {
|
||||
ActionType actionType;
|
||||
uint256 accountIdx;
|
||||
AssetAmount amount;
|
||||
uint256 primaryMarketId;
|
||||
uint256 secondaryMarketId;
|
||||
address otherAddress;
|
||||
uint256 otherAccountIdx;
|
||||
bytes data;
|
||||
}
|
||||
|
||||
enum AssetDenomination {
|
||||
Wei, // the amount is denominated in wei
|
||||
Par // the amount is denominated in par
|
||||
}
|
||||
|
||||
enum AssetReference {
|
||||
Delta, // the amount is given as a delta from the current value
|
||||
Target // the amount is given as an exact number to end up at
|
||||
}
|
||||
|
||||
struct AssetAmount {
|
||||
bool sign; // true if positive
|
||||
AssetDenomination denomination;
|
||||
AssetReference ref;
|
||||
uint256 value;
|
||||
}
|
||||
|
||||
struct D256 {
|
||||
uint256 value;
|
||||
}
|
||||
|
||||
struct Value {
|
||||
uint256 value;
|
||||
}
|
||||
|
||||
struct Price {
|
||||
uint256 value;
|
||||
}
|
||||
|
||||
struct OperatorArg {
|
||||
address operator;
|
||||
bool trusted;
|
||||
}
|
||||
|
||||
/// @dev The global risk parameters that govern the health and security of the system
|
||||
struct RiskParams {
|
||||
// Required ratio of over-collateralization
|
||||
D256 marginRatio;
|
||||
// Percentage penalty incurred by liquidated accounts
|
||||
D256 liquidationSpread;
|
||||
// Percentage of the borrower's interest fee that gets passed to the suppliers
|
||||
D256 earningsRate;
|
||||
// The minimum absolute borrow value of an account
|
||||
// There must be sufficient incentivize to liquidate undercollateralized accounts
|
||||
Value minBorrowedValue;
|
||||
}
|
||||
|
||||
/// @dev The main entry-point to Solo that allows users and contracts to manage accounts.
|
||||
/// Take one or more actions on one or more accounts. The msg.sender must be the owner or
|
||||
/// operator of all accounts except for those being liquidated, vaporized, or traded with.
|
||||
/// One call to operate() is considered a singular "operation". Account collateralization is
|
||||
/// ensured only after the completion of the entire operation.
|
||||
/// @param accounts A list of all accounts that will be used in this operation. Cannot contain
|
||||
/// duplicates. In each action, the relevant account will be referred-to by its
|
||||
/// index in the list.
|
||||
/// @param actions An ordered list of all actions that will be taken in this operation. The
|
||||
/// actions will be processed in order.
|
||||
function operate(
|
||||
AccountInfo[] calldata accounts,
|
||||
ActionArgs[] calldata actions
|
||||
)
|
||||
external;
|
||||
|
||||
// @dev Approves/disapproves any number of operators. An operator is an external address that has the
|
||||
// same permissions to manipulate an account as the owner of the account. Operators are simply
|
||||
// addresses and therefore may either be externally-owned Ethereum accounts OR smart contracts.
|
||||
// Operators are also able to act as AutoTrader contracts on behalf of the account owner if the
|
||||
// operator is a smart contract and implements the IAutoTrader interface.
|
||||
// @param args A list of OperatorArgs which have an address and a boolean. The boolean value
|
||||
// denotes whether to approve (true) or revoke approval (false) for that address.
|
||||
function setOperators(OperatorArg[] calldata args) external;
|
||||
|
||||
/// @dev Return true if a particular address is approved as an operator for an owner's accounts.
|
||||
/// Approved operators can act on the accounts of the owner as if it were the operator's own.
|
||||
/// @param owner The owner of the accounts
|
||||
/// @param operator The possible operator
|
||||
/// @return isLocalOperator True if operator is approved for owner's accounts
|
||||
function getIsLocalOperator(
|
||||
address owner,
|
||||
address operator
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isLocalOperator);
|
||||
|
||||
/// @dev Get the ERC20 token address for a market.
|
||||
/// @param marketId The market to query
|
||||
/// @return tokenAddress The token address
|
||||
function getMarketTokenAddress(
|
||||
uint256 marketId
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (address tokenAddress);
|
||||
|
||||
/// @dev Get all risk parameters in a single struct.
|
||||
/// @return riskParams All global risk parameters
|
||||
function getRiskParams()
|
||||
external
|
||||
view
|
||||
returns (RiskParams memory riskParams);
|
||||
|
||||
/// @dev Get the price of the token for a market.
|
||||
/// @param marketId The market to query
|
||||
/// @return price The price of each atomic unit of the token
|
||||
function getMarketPrice(
|
||||
uint256 marketId
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (Price memory price);
|
||||
|
||||
/// @dev Get the margin premium for a market. A margin premium makes it so that any positions that
|
||||
/// include the market require a higher collateralization to avoid being liquidated.
|
||||
/// @param marketId The market to query
|
||||
/// @return premium The market's margin premium
|
||||
function getMarketMarginPremium(uint256 marketId)
|
||||
external
|
||||
view
|
||||
returns (D256 memory premium);
|
||||
|
||||
/// @dev Get the total supplied and total borrowed values of an account adjusted by the marginPremium
|
||||
/// of each market. Supplied values are divided by (1 + marginPremium) for each market and
|
||||
/// borrowed values are multiplied by (1 + marginPremium) for each market. Comparing these
|
||||
/// adjusted values gives the margin-ratio of the account which will be compared to the global
|
||||
/// margin-ratio when determining if the account can be liquidated.
|
||||
/// @param account The account to query
|
||||
/// @return supplyValue The supplied value of the account (adjusted for marginPremium)
|
||||
/// @return borrowValue The borrowed value of the account (adjusted for marginPremium)
|
||||
function getAdjustedAccountValues(
|
||||
AccountInfo calldata account
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (Value memory supplyValue, Value memory borrowValue);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
interface IDydxBridge {
|
||||
|
||||
/// @dev This is the subset of `IDydx.ActionType` that are supported by the bridge.
|
||||
enum BridgeActionType {
|
||||
Deposit, // Deposit tokens into dydx account.
|
||||
Withdraw // Withdraw tokens from dydx account.
|
||||
}
|
||||
|
||||
struct BridgeAction {
|
||||
BridgeActionType actionType; // Action to run on dydx account.
|
||||
uint256 accountIdx; // Index in `BridgeData.accountNumbers` for this action.
|
||||
uint256 marketId; // Market to operate on.
|
||||
uint256 conversionRateNumerator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
|
||||
uint256 conversionRateDenominator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
|
||||
}
|
||||
|
||||
struct BridgeData {
|
||||
uint256[] accountNumbers; // Account number used to identify the owner's specific account.
|
||||
BridgeAction[] actions; // Actions to carry out on the owner's accounts.
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
contract IERC20Bridge {
|
||||
|
||||
/// @dev Result of a successful bridge call.
|
||||
bytes4 constant internal BRIDGE_SUCCESS = 0xdc1600f3;
|
||||
|
||||
/// @dev Emitted when a trade occurs.
|
||||
/// @param inputToken The token the bridge is converting from.
|
||||
/// @param outputToken The token the bridge is converting to.
|
||||
/// @param inputTokenAmount Amount of input token.
|
||||
/// @param outputTokenAmount Amount of output token.
|
||||
/// @param from The `from` address in `bridgeTransferFrom()`
|
||||
/// @param to The `to` address in `bridgeTransferFrom()`
|
||||
event ERC20BridgeTransfer(
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
address from,
|
||||
address to
|
||||
);
|
||||
|
||||
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
|
||||
/// @param tokenAddress The address of the ERC20 token to transfer.
|
||||
/// @param from Address to transfer asset from.
|
||||
/// @param to Address to transfer asset to.
|
||||
/// @param amount Amount of asset to transfer.
|
||||
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
|
||||
/// @return success The magic bytes `0xdc1600f3` if successful.
|
||||
function bridgeTransferFrom(
|
||||
address tokenAddress,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata bridgeData
|
||||
)
|
||||
external
|
||||
returns (bytes4 success);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
interface IEth2Dai {
|
||||
|
||||
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
|
||||
/// @param fromToken The token being sold.
|
||||
/// @param sellAmount The amount of `fromToken` token being sold.
|
||||
/// @param toToken The token being bought.
|
||||
/// @param minFillAmount Minimum amount of `toToken` token to buy.
|
||||
/// @return fillAmount Amount of `toToken` bought.
|
||||
function sellAllAmount(
|
||||
address fromToken,
|
||||
uint256 sellAmount,
|
||||
address toToken,
|
||||
uint256 minFillAmount
|
||||
)
|
||||
external
|
||||
returns (uint256 fillAmount);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.15;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
|
||||
|
||||
contract IGasToken is IERC20Token {
|
||||
|
||||
/// @dev Frees up to `value` sub-tokens
|
||||
/// @param value The amount of tokens to free
|
||||
/// @return How many tokens were freed
|
||||
function freeUpTo(uint256 value) external returns (uint256 freed);
|
||||
|
||||
/// @dev Frees up to `value` sub-tokens owned by `from`
|
||||
/// @param from The owner of tokens to spend
|
||||
/// @param value The amount of tokens to free
|
||||
/// @return How many tokens were freed
|
||||
function freeFromUpTo(address from, uint256 value) external returns (uint256 freed);
|
||||
|
||||
/// @dev Mints `value` amount of tokens
|
||||
/// @param value The amount of tokens to mint
|
||||
function mint(uint256 value) external;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
interface IKyberNetworkProxy {
|
||||
|
||||
/// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens.
|
||||
/// @param sellTokenAddress Token to sell.
|
||||
/// @param sellAmount Amount of tokens to sell.
|
||||
/// @param buyTokenAddress Token to buy.
|
||||
/// @param recipientAddress Address to send bought tokens to.
|
||||
/// @param maxBuyTokenAmount A limit on the amount of tokens to buy.
|
||||
/// @param minConversionRate The minimal conversion rate. If actual rate
|
||||
/// is lower, trade is canceled.
|
||||
/// @param walletId The wallet ID to send part of the fees
|
||||
/// @return boughtAmount Amount of tokens bought.
|
||||
function trade(
|
||||
address sellTokenAddress,
|
||||
uint256 sellAmount,
|
||||
address buyTokenAddress,
|
||||
address payable recipientAddress,
|
||||
uint256 maxBuyTokenAmount,
|
||||
uint256 minConversionRate,
|
||||
address walletId
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens
|
||||
/// using a hint for the reserve.
|
||||
/// @param sellTokenAddress Token to sell.
|
||||
/// @param sellAmount Amount of tokens to sell.
|
||||
/// @param buyTokenAddress Token to buy.
|
||||
/// @param recipientAddress Address to send bought tokens to.
|
||||
/// @param maxBuyTokenAmount A limit on the amount of tokens to buy.
|
||||
/// @param minConversionRate The minimal conversion rate. If actual rate
|
||||
/// is lower, trade is canceled.
|
||||
/// @param walletId The wallet ID to send part of the fees
|
||||
/// @param hint The hint for the selective inclusion (or exclusion) of reserves
|
||||
/// @return boughtAmount Amount of tokens bought.
|
||||
function tradeWithHint(
|
||||
address sellTokenAddress,
|
||||
uint256 sellAmount,
|
||||
address buyTokenAddress,
|
||||
address payable recipientAddress,
|
||||
uint256 maxBuyTokenAmount,
|
||||
uint256 minConversionRate,
|
||||
address payable walletId,
|
||||
bytes calldata hint
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 boughtAmount);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
interface IMStable {
|
||||
|
||||
function swap(
|
||||
address _input,
|
||||
address _output,
|
||||
uint256 _quantity,
|
||||
address _recipient
|
||||
)
|
||||
external
|
||||
returns (uint256 output);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
interface IMooniswapRegistry {
|
||||
|
||||
function pools(address token1, address token2) external view returns(address);
|
||||
}
|
||||
|
||||
|
||||
interface IMooniswap {
|
||||
|
||||
function swap(
|
||||
address fromToken,
|
||||
address destToken,
|
||||
uint256 amount,
|
||||
uint256 minReturn,
|
||||
address referral
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns(uint256 returnAmount);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
interface IShell {
|
||||
|
||||
function originSwap(
|
||||
address from,
|
||||
address to,
|
||||
uint256 fromAmount,
|
||||
uint256 minTargetAmount,
|
||||
uint256 deadline
|
||||
)
|
||||
external
|
||||
returns (uint256 toAmount);
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
|
||||
interface IUniswapExchange {
|
||||
|
||||
/// @dev Buys at least `minTokensBought` tokens with ETH and transfer them
|
||||
/// to `recipient`.
|
||||
/// @param minTokensBought The minimum number of tokens to buy.
|
||||
/// @param deadline Time when this order expires.
|
||||
/// @param recipient Who to transfer the tokens to.
|
||||
/// @return tokensBought Amount of tokens bought.
|
||||
function ethToTokenTransferInput(
|
||||
uint256 minTokensBought,
|
||||
uint256 deadline,
|
||||
address recipient
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 tokensBought);
|
||||
|
||||
/// @dev Buys at least `minEthBought` ETH with tokens.
|
||||
/// @param tokensSold Amount of tokens to sell.
|
||||
/// @param minEthBought The minimum amount of ETH to buy.
|
||||
/// @param deadline Time when this order expires.
|
||||
/// @return ethBought Amount of tokens bought.
|
||||
function tokenToEthSwapInput(
|
||||
uint256 tokensSold,
|
||||
uint256 minEthBought,
|
||||
uint256 deadline
|
||||
)
|
||||
external
|
||||
returns (uint256 ethBought);
|
||||
|
||||
/// @dev Buys at least `minTokensBought` tokens with the exchange token
|
||||
/// and transfer them to `recipient`.
|
||||
/// @param minTokensBought The minimum number of tokens to buy.
|
||||
/// @param minEthBought The minimum amount of intermediate ETH to buy.
|
||||
/// @param deadline Time when this order expires.
|
||||
/// @param recipient Who to transfer the tokens to.
|
||||
/// @param toTokenAddress The token being bought.
|
||||
/// @return tokensBought Amount of tokens bought.
|
||||
function tokenToTokenTransferInput(
|
||||
uint256 tokensSold,
|
||||
uint256 minTokensBought,
|
||||
uint256 minEthBought,
|
||||
uint256 deadline,
|
||||
address recipient,
|
||||
address toTokenAddress
|
||||
)
|
||||
external
|
||||
returns (uint256 tokensBought);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
|
||||
import "./IUniswapExchange.sol";
|
||||
|
||||
|
||||
interface IUniswapExchangeFactory {
|
||||
|
||||
/// @dev Get the exchange for a token.
|
||||
/// @param tokenAddress The address of the token contract.
|
||||
function getExchange(address tokenAddress)
|
||||
external
|
||||
view
|
||||
returns (address);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
interface IUniswapV2Router01 {
|
||||
|
||||
/// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path.
|
||||
/// The first element of path is the input token, the last is the output token, and any intermediate elements represent
|
||||
/// intermediate pairs to trade through (if, for example, a direct pair does not exist).
|
||||
/// @param amountIn The amount of input tokens to send.
|
||||
/// @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.
|
||||
/// @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
|
||||
/// @param to Recipient of the output tokens.
|
||||
/// @param deadline Unix timestamp after which the transaction will revert.
|
||||
/// @return amounts The input token amount and all subsequent output token amounts.
|
||||
function swapExactTokensForTokens(
|
||||
uint amountIn,
|
||||
uint amountOutMin,
|
||||
address[] calldata path,
|
||||
address to,
|
||||
uint deadline
|
||||
) external returns (uint[] memory amounts);
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
|
||||
import "../src/bridges/BancorBridge.sol";
|
||||
import "../src/interfaces/IBancorNetwork.sol";
|
||||
|
||||
|
||||
contract TestEventsRaiser {
|
||||
|
||||
event TokenTransfer(
|
||||
address token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
event TokenApprove(
|
||||
address spender,
|
||||
uint256 allowance
|
||||
);
|
||||
|
||||
event ConvertByPathInput(
|
||||
uint amountIn,
|
||||
uint amountOutMin,
|
||||
address toTokenAddress,
|
||||
address to,
|
||||
address feeRecipient,
|
||||
uint256 feeAmount
|
||||
);
|
||||
|
||||
function raiseTokenTransfer(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
{
|
||||
emit TokenTransfer(
|
||||
msg.sender,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
function raiseTokenApprove(address spender, uint256 allowance) external {
|
||||
emit TokenApprove(spender, allowance);
|
||||
}
|
||||
|
||||
function raiseConvertByPathInput(
|
||||
uint amountIn,
|
||||
uint amountOutMin,
|
||||
address toTokenAddress,
|
||||
address to,
|
||||
address feeRecipient,
|
||||
uint256 feeAmount
|
||||
) external
|
||||
{
|
||||
emit ConvertByPathInput(
|
||||
amountIn,
|
||||
amountOutMin,
|
||||
toTokenAddress,
|
||||
to,
|
||||
feeRecipient,
|
||||
feeAmount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @dev A minimalist ERC20 token.
|
||||
contract TestToken {
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
mapping (address => uint256) public balances;
|
||||
string private _nextRevertReason;
|
||||
|
||||
/// @dev Set the balance for `owner`.
|
||||
function setBalance(address owner, uint256 balance)
|
||||
external
|
||||
payable
|
||||
{
|
||||
balances[owner] = balance;
|
||||
}
|
||||
|
||||
/// @dev Just emits a TokenTransfer event on the caller
|
||||
function transfer(address to, uint256 amount)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Just emits a TokenApprove event on the caller
|
||||
function approve(address spender, uint256 allowance)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address, address) external view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @dev Retrieve the balance for `owner`.
|
||||
function balanceOf(address owner)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return balances[owner];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @dev Mock the BancorNetwork contract
|
||||
contract TestBancorNetwork is
|
||||
IBancorNetwork
|
||||
{
|
||||
string private _nextRevertReason;
|
||||
|
||||
/// @dev Set the revert reason for `swapExactTokensForTokens`.
|
||||
function setRevertReason(string calldata reason)
|
||||
external
|
||||
{
|
||||
_nextRevertReason = reason;
|
||||
}
|
||||
|
||||
function convertByPath(
|
||||
address[] calldata _path,
|
||||
uint256 _amount,
|
||||
uint256 _minReturn,
|
||||
address _beneficiary,
|
||||
address _affiliateAccount,
|
||||
uint256 _affiliateFee
|
||||
) external payable returns (uint256)
|
||||
{
|
||||
_revertIfReasonExists();
|
||||
|
||||
TestEventsRaiser(msg.sender).raiseConvertByPathInput(
|
||||
// tokens sold
|
||||
_amount,
|
||||
// tokens bought
|
||||
_minReturn,
|
||||
// output token
|
||||
_path[_path.length - 1],
|
||||
// recipient
|
||||
_beneficiary,
|
||||
// fee recipient
|
||||
_affiliateAccount,
|
||||
// fee amount
|
||||
_affiliateFee
|
||||
);
|
||||
}
|
||||
|
||||
function _revertIfReasonExists()
|
||||
private
|
||||
view
|
||||
{
|
||||
if (bytes(_nextRevertReason).length != 0) {
|
||||
revert(_nextRevertReason);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @dev BancorBridge overridden to mock tokens and BancorNetwork
|
||||
contract TestBancorBridge is
|
||||
BancorBridge,
|
||||
TestEventsRaiser
|
||||
{
|
||||
|
||||
// Token address to TestToken instance.
|
||||
mapping (address => TestToken) private _testTokens;
|
||||
// TestRouter instance.
|
||||
TestBancorNetwork private _testNetwork;
|
||||
|
||||
constructor() public {
|
||||
_testNetwork = new TestBancorNetwork();
|
||||
}
|
||||
|
||||
function setNetworkRevertReason(string calldata revertReason)
|
||||
external
|
||||
{
|
||||
_testNetwork.setRevertReason(revertReason);
|
||||
}
|
||||
|
||||
/// @dev Sets the balance of this contract for an existing token.
|
||||
function setTokenBalance(address tokenAddress, uint256 balance)
|
||||
external
|
||||
{
|
||||
TestToken token = _testTokens[tokenAddress];
|
||||
token.setBalance(address(this), balance);
|
||||
}
|
||||
|
||||
/// @dev Create a new token
|
||||
/// @param tokenAddress The token address. If zero, one will be created.
|
||||
function createToken(
|
||||
address tokenAddress
|
||||
)
|
||||
external
|
||||
returns (TestToken token)
|
||||
{
|
||||
token = TestToken(tokenAddress);
|
||||
if (tokenAddress == address(0)) {
|
||||
token = new TestToken();
|
||||
}
|
||||
_testTokens[address(token)] = token;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
function getNetworkAddress()
|
||||
external
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return address(_testNetwork);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../src/bridges/ChaiBridge.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/ERC20Token.sol";
|
||||
|
||||
|
||||
contract TestChaiDai is
|
||||
ERC20Token
|
||||
{
|
||||
address private constant ALWAYS_REVERT_ADDRESS = address(1);
|
||||
|
||||
function draw(
|
||||
address from,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
{
|
||||
if (from == ALWAYS_REVERT_ADDRESS) {
|
||||
revert();
|
||||
}
|
||||
balances[msg.sender] += amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract TestChaiBridge is
|
||||
ChaiBridge
|
||||
{
|
||||
address public testChaiDai;
|
||||
address private constant ALWAYS_REVERT_ADDRESS = address(1);
|
||||
|
||||
constructor()
|
||||
public
|
||||
{
|
||||
testChaiDai = address(new TestChaiDai());
|
||||
}
|
||||
|
||||
function _getDaiAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return testChaiDai;
|
||||
}
|
||||
|
||||
function _getChaiAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return testChaiDai;
|
||||
}
|
||||
|
||||
function _getERC20BridgeProxyAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender;
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../src/bridges/DexForwarderBridge.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
|
||||
|
||||
interface ITestDexForwarderBridge {
|
||||
event BridgeTransferFromCalled(
|
||||
address caller,
|
||||
uint256 inputTokenBalance,
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
event TokenTransferCalled(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
function emitBridgeTransferFromCalled(
|
||||
address caller,
|
||||
uint256 inputTokenBalance,
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) external;
|
||||
|
||||
function emitTokenTransferCalled(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) external;
|
||||
}
|
||||
|
||||
|
||||
interface ITestDexForwarderBridgeTestToken {
|
||||
|
||||
function transfer(address to, uint256 amount)
|
||||
external
|
||||
returns (bool);
|
||||
|
||||
function mint(address to, uint256 amount)
|
||||
external;
|
||||
|
||||
function balanceOf(address owner) external view returns (uint256);
|
||||
}
|
||||
|
||||
|
||||
contract TestDexForwarderBridgeTestBridge {
|
||||
|
||||
bytes4 private _returnCode;
|
||||
string private _revertError;
|
||||
uint256 private _transferAmount;
|
||||
ITestDexForwarderBridge private _testContract;
|
||||
|
||||
constructor(bytes4 returnCode, string memory revertError) public {
|
||||
_testContract = ITestDexForwarderBridge(msg.sender);
|
||||
_returnCode = returnCode;
|
||||
_revertError = revertError;
|
||||
}
|
||||
|
||||
function setTransferAmount(uint256 amount) external {
|
||||
_transferAmount = amount;
|
||||
}
|
||||
|
||||
function bridgeTransferFrom(
|
||||
address outputToken,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory bridgeData
|
||||
)
|
||||
public
|
||||
returns (bytes4 success)
|
||||
{
|
||||
if (bytes(_revertError).length != 0) {
|
||||
revert(_revertError);
|
||||
}
|
||||
address inputToken = abi.decode(bridgeData, (address));
|
||||
_testContract.emitBridgeTransferFromCalled(
|
||||
msg.sender,
|
||||
ITestDexForwarderBridgeTestToken(inputToken).balanceOf(address(this)),
|
||||
inputToken,
|
||||
outputToken,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
ITestDexForwarderBridgeTestToken(outputToken).mint(to, _transferAmount);
|
||||
return _returnCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract TestDexForwarderBridgeTestToken {
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) public balanceOf;
|
||||
ITestDexForwarderBridge private _testContract;
|
||||
|
||||
constructor() public {
|
||||
_testContract = ITestDexForwarderBridge(msg.sender);
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
balanceOf[msg.sender] = balanceOf[msg.sender].safeSub(amount);
|
||||
balanceOf[to] = balanceOf[to].safeAdd(amount);
|
||||
_testContract.emitTokenTransferCalled(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function mint(address owner, uint256 amount)
|
||||
external
|
||||
{
|
||||
balanceOf[owner] = balanceOf[owner].safeAdd(amount);
|
||||
}
|
||||
|
||||
function setBalance(address owner, uint256 amount)
|
||||
external
|
||||
{
|
||||
balanceOf[owner] = amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract TestDexForwarderBridge is
|
||||
ITestDexForwarderBridge,
|
||||
DexForwarderBridge
|
||||
{
|
||||
address private AUTHORIZED_ADDRESS; // solhint-disable-line var-name-mixedcase
|
||||
|
||||
function setAuthorized(address authorized)
|
||||
public
|
||||
{
|
||||
AUTHORIZED_ADDRESS = authorized;
|
||||
}
|
||||
|
||||
function createBridge(
|
||||
bytes4 returnCode,
|
||||
string memory revertError
|
||||
)
|
||||
public
|
||||
returns (address bridge)
|
||||
{
|
||||
return address(new TestDexForwarderBridgeTestBridge(returnCode, revertError));
|
||||
}
|
||||
|
||||
function createToken() public returns (address token) {
|
||||
return address(new TestDexForwarderBridgeTestToken());
|
||||
}
|
||||
|
||||
function setTokenBalance(address token, address owner, uint256 amount) public {
|
||||
TestDexForwarderBridgeTestToken(token).setBalance(owner, amount);
|
||||
}
|
||||
|
||||
function setBridgeTransferAmount(address bridge, uint256 amount) public {
|
||||
TestDexForwarderBridgeTestBridge(bridge).setTransferAmount(amount);
|
||||
}
|
||||
|
||||
function emitBridgeTransferFromCalled(
|
||||
address caller,
|
||||
uint256 inputTokenBalance,
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
public
|
||||
{
|
||||
emit BridgeTransferFromCalled(
|
||||
caller,
|
||||
inputTokenBalance,
|
||||
inputToken,
|
||||
outputToken,
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
function emitTokenTransferCalled(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
public
|
||||
{
|
||||
emit TokenTransferCalled(
|
||||
from,
|
||||
to,
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
||||
function balanceOf(address token, address owner) public view returns (uint256) {
|
||||
return TestDexForwarderBridgeTestToken(token).balanceOf(owner);
|
||||
}
|
||||
|
||||
function _getGstAddress()
|
||||
internal
|
||||
view
|
||||
returns (address gst)
|
||||
{
|
||||
return address(0);
|
||||
}
|
||||
|
||||
function _getERC20BridgeProxyAddress()
|
||||
internal
|
||||
view
|
||||
returns (address erc20BridgeProxyAddress)
|
||||
{
|
||||
return AUTHORIZED_ADDRESS;
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 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.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "../src/bridges/DydxBridge.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract TestDydxBridgeToken {
|
||||
|
||||
uint256 private constant INIT_HOLDER_BALANCE = 10 * 10**18; // 10 tokens
|
||||
mapping (address => uint256) private _balances;
|
||||
|
||||
/// @dev Sets initial balance of token holders.
|
||||
constructor(address[] memory holders)
|
||||
public
|
||||
{
|
||||
for (uint256 i = 0; i != holders.length; ++i) {
|
||||
_balances[holders[i]] = INIT_HOLDER_BALANCE;
|
||||
}
|
||||
_balances[msg.sender] = INIT_HOLDER_BALANCE;
|
||||
}
|
||||
|
||||
/// @dev Basic transferFrom implementation.
|
||||
function transferFrom(address from, address to, uint256 amount)
|
||||
external
|
||||
returns (bool)
|
||||
{
|
||||
if (_balances[from] < amount || _balances[to] + amount < _balances[to]) {
|
||||
return false;
|
||||
}
|
||||
_balances[from] -= amount;
|
||||
_balances[to] += amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Returns balance of `holder`.
|
||||
function balanceOf(address holder)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return _balances[holder];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// solhint-disable space-after-comma
|
||||
contract TestDydxBridge is
|
||||
IDydx,
|
||||
DydxBridge
|
||||
{
|
||||
|
||||
address private constant ALWAYS_REVERT_ADDRESS = address(1);
|
||||
address private _testTokenAddress;
|
||||
bool private _shouldRevertOnOperate;
|
||||
|
||||
event OperateAccount(
|
||||
address owner,
|
||||
uint256 number
|
||||
);
|
||||
|
||||
event OperateAction(
|
||||
ActionType actionType,
|
||||
uint256 accountIdx,
|
||||
bool amountSign,
|
||||
AssetDenomination amountDenomination,
|
||||
AssetReference amountRef,
|
||||
uint256 amountValue,
|
||||
uint256 primaryMarketId,
|
||||
uint256 secondaryMarketId,
|
||||
address otherAddress,
|
||||
uint256 otherAccountId,
|
||||
bytes data
|
||||
);
|
||||
|
||||
constructor(address[] memory holders)
|
||||
public
|
||||
{
|
||||
// Deploy a test token. This represents the asset being deposited/withdrawn from dydx.
|
||||
_testTokenAddress = address(new TestDydxBridgeToken(holders));
|
||||
}
|
||||
|
||||
/// @dev Simulates `operate` in dydx contract.
|
||||
/// Emits events so that arguments can be validated client-side.
|
||||
function operate(
|
||||
AccountInfo[] calldata accounts,
|
||||
ActionArgs[] calldata actions
|
||||
)
|
||||
external
|
||||
{
|
||||
if (_shouldRevertOnOperate) {
|
||||
revert("TestDydxBridge/SHOULD_REVERT_ON_OPERATE");
|
||||
}
|
||||
|
||||
for (uint i = 0; i < accounts.length; ++i) {
|
||||
emit OperateAccount(
|
||||
accounts[i].owner,
|
||||
accounts[i].number
|
||||
);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < actions.length; ++i) {
|
||||
emit OperateAction(
|
||||
actions[i].actionType,
|
||||
actions[i].accountIdx,
|
||||
actions[i].amount.sign,
|
||||
actions[i].amount.denomination,
|
||||
actions[i].amount.ref,
|
||||
actions[i].amount.value,
|
||||
actions[i].primaryMarketId,
|
||||
actions[i].secondaryMarketId,
|
||||
actions[i].otherAddress,
|
||||
actions[i].otherAccountIdx,
|
||||
actions[i].data
|
||||
);
|
||||
|
||||
if (actions[i].actionType == IDydx.ActionType.Withdraw) {
|
||||
require(
|
||||
IERC20Token(_testTokenAddress).transferFrom(
|
||||
address(this),
|
||||
actions[i].otherAddress,
|
||||
actions[i].amount.value
|
||||
),
|
||||
"TestDydxBridge/WITHDRAW_FAILED"
|
||||
);
|
||||
} else if (actions[i].actionType == IDydx.ActionType.Deposit) {
|
||||
require(
|
||||