├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .solcover.js ├── .soliumignore ├── .soliumrc.json ├── .travis.yml ├── AaveRegistry.full.abi ├── AaveRegistry.full.bin ├── AaveRegistry.full.sol ├── BalancerHelper.full.abi ├── BalancerHelper.full.bin ├── BalancerHelper.full.sol ├── BancorFinder.full.abi ├── BancorFinder.full.bin ├── BancorFinder.full.sol ├── CompoundRegistry.full.abi ├── CompoundRegistry.full.bin ├── CompoundRegistry.full.sol ├── KyberReserves.md ├── LICENSE ├── OneSplit.full.abi ├── OneSplit.full.bin ├── OneSplit.full.sol ├── OneSplitAudit.full.abi ├── OneSplitAudit.full.bin ├── OneSplitAudit.full.sol ├── OneSplitView.full.abi ├── OneSplitView.full.bin ├── OneSplitView.full.sol ├── README.md ├── contracts ├── 1inchProtocol-audit.pdf ├── AaveRegistry.sol ├── BalancerHelper.sol ├── BalancerLib.sol ├── BancorFinder.sol ├── CompoundRegistry.sol ├── IOneSplit.sol ├── Migrations.sol ├── OneSplit.sol ├── OneSplitAave.sol ├── OneSplitAudit.sol ├── OneSplitBase.sol ├── OneSplitBdai.sol ├── OneSplitChai.sol ├── OneSplitCompound.sol ├── OneSplitDMM.sol ├── OneSplitFulcrum.sol ├── OneSplitIdle.sol ├── OneSplitIearn.sol ├── OneSplitMStable.sol ├── OneSplitMooniswapPoolToken.sol ├── OneSplitWeth.sol ├── UniversalERC20.sol └── interface │ ├── IAaveRegistry.sol │ ├── IAaveToken.sol │ ├── IBalancerPool.sol │ ├── IBalancerRegistry.sol │ ├── IBancorContractRegistry.sol │ ├── IBancorConverterRegistry.sol │ ├── IBancorEtherToken.sol │ ├── IBancorFinder.sol │ ├── IBancorNetwork.sol │ ├── IBancorNetworkPathFinder.sol │ ├── IBdai.sol │ ├── IChai.sol │ ├── ICompound.sol │ ├── ICompoundRegistry.sol │ ├── ICurve.sol │ ├── IDForceSwap.sol │ ├── IDMM.sol │ ├── IFulcrum.sol │ ├── IIdle.sol │ ├── IIearn.sol │ ├── IKyberHintHandler.sol │ ├── IKyberNetworkContract.sol │ ├── IKyberNetworkProxy.sol │ ├── IKyberOasisReserve.sol │ ├── IKyberStorage.sol │ ├── IMStable.sol │ ├── IMooniswap.sol │ ├── IOasisExchange.sol │ ├── IShell.sol │ ├── ISmartToken.sol │ ├── ISmartTokenConverter.sol │ ├── ISmartTokenFormula.sol │ ├── ISmartTokenRegistry.sol │ ├── IUniswapExchange.sol │ ├── IUniswapFactory.sol │ ├── IUniswapV2Exchange.sol │ ├── IUniswapV2Factory.sol │ └── IWETH.sol ├── img ├── howitworks.png └── howtouseit.png ├── migrations └── 1_initial_migration.js ├── package.json ├── scripts ├── coverage.sh └── test.sh ├── solhint.json ├── test └── OneSplit.js ├── truffle-config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | truffle-config.js 3 | js/ 4 | test/helpers 5 | coverage/ -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends" : [ 3 | "standard", 4 | "plugin:promise/recommended" 5 | ], 6 | "plugins": [ 7 | "promise" 8 | ], 9 | "env": { 10 | "browser" : true, 11 | "node" : true, 12 | "mocha" : true, 13 | "jest" : true 14 | }, 15 | "globals" : { 16 | "artifacts": false, 17 | "contract": false, 18 | "assert": false, 19 | "web3": false 20 | }, 21 | "rules": { 22 | 23 | // Strict mode 24 | "strict": [2, "global"], 25 | 26 | // Code style 27 | "indent": [2, 4], 28 | "quotes": [2, "single"], 29 | "semi": ["error", "always"], 30 | "space-before-function-paren": ["error", "always"], 31 | "no-use-before-define": 0, 32 | "no-unused-expressions": "off", 33 | "eqeqeq": [2, "smart"], 34 | "dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}], 35 | "no-redeclare": [2, {"builtinGlobals": true}], 36 | "no-trailing-spaces": [2, { "skipBlankLines": true }], 37 | "eol-last": 1, 38 | "comma-spacing": [2, {"before": false, "after": true}], 39 | "camelcase": [2, {"properties": "always"}], 40 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"], 41 | "comma-dangle": [1, "always-multiline"], 42 | "no-dupe-args": 2, 43 | "no-dupe-keys": 2, 44 | "no-debugger": 0, 45 | "no-undef": 2, 46 | "object-curly-spacing": [2, "always"], 47 | "max-len": [2, 200, 2], 48 | "generator-star-spacing": ["error", "before"], 49 | "promise/avoid-new": 0, 50 | "promise/always-return": 0 51 | } 52 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | coverage.json 4 | build/ 5 | .env -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1inch/1inchProtocol/811f7b69b67d1d9657e3e9c18a2e97f3e2b2b33a/.prettierignore -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": false 4 | } 5 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testrpcOptions: '--port 8555 ' + 3 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,1000000000000000000000000" ' + 4 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,1000000000000000000000000" ' + 5 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,1000000000000000000000000" ' + 6 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501203,1000000000000000000000000" ' + 7 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501204,1000000000000000000000000" ' + 8 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501205,1000000000000000000000000" ' + 9 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501206,1000000000000000000000000" ' + 10 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501207,1000000000000000000000000" ' + 11 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501208,1000000000000000000000000" ' + 12 | ' --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000"', 13 | copyPackages: ['openzeppelin-solidity'], 14 | norpc: true, 15 | skipFiles: ['Migrations.sol'] 16 | } 17 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | OneSplit.full.sol 3 | OneSplitAudit.full.sol 4 | contracts/interface/IChai.sol 5 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:all", 3 | "plugins": ["security"], 4 | "rules": { 5 | "error-reason": "off", 6 | "indentation": ["error", 4], 7 | "lbrace": "off", 8 | "linebreak-style": ["error", "unix"], 9 | "max-len": ["error", 139], 10 | "no-constant": ["error"], 11 | "no-empty-blocks": "off", 12 | "quotes": ["error", "double"], 13 | "uppercase": "off", 14 | "visibility-first": "error", 15 | "arg-overflow": ["error", 5], 16 | "function-order": "off", 17 | 18 | "security/enforce-explicit-visibility": ["error"], 19 | "security/no-block-members": ["off"], 20 | "security/no-inline-assembly": ["warning"] 21 | } 22 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # https://github.com/sc-forks/solidity-coverage/blob/master/docs/faq.md 3 | # 4 | 5 | sudo: required 6 | dist: trusty 7 | language: node_js 8 | node_js: 9 | - '10' 10 | install: 11 | - yarn 12 | script: 13 | - yarn run lint 14 | - yarn run test 15 | after_script: 16 | - yarn run coverage 17 | branches: 18 | only: 19 | - master 20 | -------------------------------------------------------------------------------- /AaveRegistry.full.abi: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"aTokenByToken","outputs":[{"internalType":"contract IAaveToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IAaveToken","name":"aToken","type":"address"}],"name":"addAToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IAaveToken[]","name":"cTokens","type":"address[]"}],"name":"addATokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IAaveToken","name":"aToken","type":"address"}],"name":"tokenByAToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /AaveRegistry.full.bin: -------------------------------------------------------------------------------- 1 | 608060405260006100176001600160e01b0361006616565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006a565b3390565b610681806100796000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b1461016f5780638f32d59b14610177578063a8e6574214610193578063f2fde38b146101b957610088565b806310b1f5261461008d5780634781b14e146100b55780635f5418f314610125578063715018a614610167575b600080fd5b6100b3600480360360208110156100a357600080fd5b50356001600160a01b03166101df565b005b6100b3600480360360208110156100cb57600080fd5b8101906020810181356401000000008111156100e657600080fd5b8201836020820111156100f857600080fd5b8035906020019184602083028401116401000000008311171561011a57600080fd5b5090925090506102d7565b61014b6004803603602081101561013b57600080fd5b50356001600160a01b031661035a565b604080516001600160a01b039092168252519081900360200190f35b6100b36103b0565b61014b610441565b61017f610450565b604080519115158252519081900360200190f35b61014b600480360360208110156101a957600080fd5b50356001600160a01b0316610474565b6100b3600480360360208110156101cf57600080fd5b50356001600160a01b03166104d5565b6101e7610450565b610226576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b6000816001600160a01b03166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561026157600080fd5b505afa158015610275573d6000803e3d6000fd5b505050506040513d602081101561028b57600080fd5b50516001600160a01b0392831660008181526001602090815260408083208054979095166001600160a01b03199788168117909555938252600290529190912080549093161790915550565b6102df610450565b61031e576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b60005b818110156103555761034d83838381811061033857fe5b905060200201356001600160a01b03166101df565b600101610321565b505050565b600061036e826001600160a01b0316610528565b1561038e5750733a3a65aab0dd2a17e3f1947ba16138cd37d08c046103ab565b506001600160a01b03808216600090815260026020526040902054165b919050565b6103b8610450565b6103f7576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b600080546001600160a01b0316610465610562565b6001600160a01b031614905090565b60006001600160a01b038216733a3a65aab0dd2a17e3f1947ba16138cd37d08c0414156104b6575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6103ab565b506001600160a01b039081166000908152600160205260409020541690565b6104dd610450565b61051c576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b61052581610566565b50565b60006001600160a01b038216158061055c57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b3390565b6001600160a01b0381166105ab5760405162461bcd60e51b81526004018080602001828103825260268152602001806106076026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a265627a7a72315820b212ee2f131114b26e30f778df74f958b98d4ebeca95cd586f997bd961a5557264736f6c63430005110032 -------------------------------------------------------------------------------- /BalancerHelper.full.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"internalType":"contract IBalancerPool","name":"pool","type":"address"},{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"getReturns","outputs":[{"internalType":"uint256[]","name":"rets","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"}] -------------------------------------------------------------------------------- /BalancerHelper.full.bin: -------------------------------------------------------------------------------- 1 | 608060405234801561001057600080fd5b50610a8e806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806340e10bcc14610030575b600080fd5b6100c16004803603608081101561004657600080fd5b6001600160a01b038235811692602081013582169260408201359092169181019060808101606082013564010000000081111561008257600080fd5b82018360208201111561009457600080fd5b803590602001918460208302840111640100000000831117156100b657600080fd5b509092509050610111565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156100fd5781810151838201526020016100e5565b505050509050019250505060405180910390f35b60606000866001600160a01b031663d4cadf686040518163ffffffff1660e01b815260040160206040518083038186803b15801561014e57600080fd5b505afa158015610162573d6000803e3d6000fd5b505050506040513d602081101561017857600080fd5b50516040805163f8b2cb4f60e01b81526001600160a01b0389811660048301529151929350600092918a169163f8b2cb4f91602480820192602092909190829003018186803b1580156101ca57600080fd5b505afa1580156101de573d6000803e3d6000fd5b505050506040513d60208110156101f457600080fd5b50516040805163f8b2cb4f60e01b81526001600160a01b0389811660048301529151929350600092918b169163f8b2cb4f91602480820192602092909190829003018186803b15801561024657600080fd5b505afa15801561025a573d6000803e3d6000fd5b505050506040513d602081101561027057600080fd5b505160408051634a46c67360e11b81526001600160a01b038b811660048301529151929350600092918c169163948d8ce691602480820192602092909190829003018186803b1580156102c257600080fd5b505afa1580156102d6573d6000803e3d6000fd5b505050506040513d60208110156102ec57600080fd5b505160408051634a46c67360e11b81526001600160a01b038b811660048301529151929350600092918d169163948d8ce691602480820192602092909190829003018186803b15801561033e57600080fd5b505afa158015610352573d6000803e3d6000fd5b505050506040513d602081101561036857600080fd5b50516040805189815260208a8102820101909152909150878015610396578160200160208202803883390190505b50955060005b87811080156103d05750846103cd60028b8b858181106103b857fe5b9050602002013561042390919063ffffffff16565b11155b15610414576103f5858486858d8d878181106103e857fe5b905060200201358b610485565b87828151811061040157fe5b602090810291909101015260010161039c565b50505050505095945050505050565b6000826104325750600061047f565b8282028284828161043f57fe5b041461047c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610a396021913960400191505060405180910390fd5b90505b92915050565b600080610492878661051e565b905060006104a8670de0b6b3a764000085610631565b90506104b48582610693565b905060006104cb8a6104c68c85610755565b61051e565b9050806104de5760009350505050610514565b60006104ea82856107a2565b90506000610500670de0b6b3a764000083610631565b905061050c8a82610693565b955050505050505b9695505050505050565b600081610561576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b670de0b6b3a764000083028315806105895750670de0b6b3a764000084828161058657fe5b04145b6105cd576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b6002830481018181101561061b576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b600084828161062657fe5b049695505050505050565b600080600061064085856108b0565b91509150801561068b576040805162461bcd60e51b81526020600482015260116024820152704552525f5355425f554e444552464c4f5760781b604482015290519081900360640190fd5b509392505050565b60008282028315806106ad5750828482816106aa57fe5b04145b6106f1576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6706f05b59d3b20000810181811015610744576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6000670de0b6b3a764000082610626565b60008282018381101561047c576040805162461bcd60e51b815260206004820152601060248201526f4552525f4144445f4f564552464c4f5760801b604482015290519081900360640190fd5b600060018310156107f2576040805162461bcd60e51b81526020600482015260156024820152744552525f42504f575f424153455f544f4f5f4c4f5760581b604482015290519081900360640190fd5b671bc16d674ec7ffff831115610848576040805162461bcd60e51b815260206004820152601660248201527508aa4a4be84a09eaebe8482a68abea89e9ebe90928e960531b604482015290519081900360640190fd5b6000610853836108d5565b905060006108618483610631565b9050600061087786610872856108f0565b6108fe565b90508161088857925061047f915050565b600061089987846305f5e100610955565b90506108a58282610693565b979650505050505050565b6000808284106108c657505080820360006108ce565b505081810360015b9250929050565b6000670de0b6b3a76400006108e9836108f0565b0292915050565b670de0b6b3a7640000900490565b6000806002830661091757670de0b6b3a7640000610919565b835b90506002830492505b821561047c576109328485610693565b9350600283061561094a576109478185610693565b90505b600283049250610922565b600082818061096c87670de0b6b3a76400006108b0565b9092509050670de0b6b3a764000080600060015b888410610a29576000670de0b6b3a7640000820290506000806109b48a6109af85670de0b6b3a7640000610631565b6108b0565b915091506109cb876109c6848c610693565b610693565b96506109d7878461051e565b9650866109e657505050610a29565b87156109f0579315935b80156109fa579315935b8415610a1157610a0a8688610631565b9550610a1e565b610a1b8688610755565b95505b505050600101610980565b5090999850505050505050505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a265627a7a72315820e7ae9c75954fab1d82996d4faa630feb235495a01f9cca2a413e065ba7828eea64736f6c63430005110032 -------------------------------------------------------------------------------- /BancorFinder.full.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"}],"name":"buildBancorPath","outputs":[{"internalType":"address[]","name":"path","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"}] -------------------------------------------------------------------------------- /BancorFinder.full.bin: -------------------------------------------------------------------------------- 1 | 608060405234801561001057600080fd5b506108b8806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063fa8f6d1314610030575b600080fd5b61005e6004803603604081101561004657600080fd5b506001600160a01b03813581169160200135166100ae565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561009a578181015183820152602001610082565b505050509050019250505060405180910390f35b6060816001600160a01b0316836001600160a01b031614156100df5750604080516000815260208101909152610844565b6100f1836001600160a01b031661084a565b1561010e5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92505b610120826001600160a01b031661084a565b1561013d5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee91505b6001600160a01b038316731f573d6fb3f13d689ff844b4ce37794d79a7ff1c148061018457506001600160a01b038216731f573d6fb3f13d689ff844b4ce37794d79a7ff1c145b156101af576040805160038082526080820190925290602082016060803883390190505090506101d1565b60408051600580825260c08201909252906020820160a0803883390190505090505b60008060007352ae12abe5d8bd778bd5397f99ca900624cfadd46001600160a01b031663bb34534c6040518163ffffffff1660e01b815260040180807f42616e636f72436f6e7665727465725265676973747279000000000000000000815250602001905060206040518083038186803b15801561024e57600080fd5b505afa158015610262573d6000803e3d6000fd5b505050506040513d602081101561027857600080fd5b505190506001600160a01b038616731f573d6fb3f13d689ff844b4ce37794d79a7ff1c1461043657600060606001600160a01b0380841690620186a090636b625ad960e11b906102c9908c1661084a565b6102d3578a6102e9565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b604080516001600160a01b039092166024830152600060448084019190915281518084039091018152606490920181526020820180516001600160e01b03166001600160e01b0319909416939093178352518151919290918291908083835b602083106103675780518252601f199092019160209182019101610348565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d80600081146103c8576040519150601f19603f3d011682016040523d82523d6000602084013e6103cd565b606091505b5091509150816103f65760408051600080825260208201909252905b5095505050505050610844565b80806020019051602081101561040b57600080fd5b505194506001600160a01b0385166104335760408051600080825260208201909252906103e9565b50505b6001600160a01b038516731f573d6fb3f13d689ff844b4ce37794d79a7ff1c146105e757600060606001600160a01b0380841690620186a090636b625ad960e11b90610483908b1661084a565b61048d57896104a3565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b604080516001600160a01b039092166024830152600060448084019190915281518084039091018152606490920181526020820180516001600160e01b03166001600160e01b0319909416939093178352518151919290918291908083835b602083106105215780518252601f199092019160209182019101610502565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d8060008114610582576040519150601f19603f3d011682016040523d82523d6000602084013e610587565b606091505b5091509150816105a75760408051600080825260208201909252906103e9565b8080602001905160208110156105bc57600080fd5b505193506001600160a01b0384166105e45760408051600080825260208201909252906103e9565b50505b6001600160a01b038516731f573d6fb3f13d689ff844b4ce37794d79a7ff1c14156106ab57858460008151811061061a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828460018151811061064857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050731f573d6fb3f13d689ff844b4ce37794d79a7ff1c8460028151811061068a57fe5b6001600160a01b039092166020928302919091019091015250610844915050565b6001600160a01b038616731f573d6fb3f13d689ff844b4ce37794d79a7ff1c141561074e57731f573d6fb3f13d689ff844b4ce37794d79a7ff1c846000815181106106f257fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818460018151811061072057fe5b60200260200101906001600160a01b031690816001600160a01b031681525050848460028151811061068a57fe5b858460008151811061075c57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828460018151811061078a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050731f573d6fb3f13d689ff844b4ce37794d79a7ff1c846002815181106107cc57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081846003815181106107fa57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050848460048151811061082857fe5b6001600160a01b03909216602092830291909101909101525050505b92915050565b60006001600160a01b038216158061084457506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee149291505056fea265627a7a72315820c9a4717cfd857e00999bd9a99f85e5e734fb9d10351f8d6b3fdaa50e9b85ec2d64736f6c63430005110032 -------------------------------------------------------------------------------- /CompoundRegistry.full.abi: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"constant":false,"inputs":[{"internalType":"contract ICompoundToken","name":"cToken","type":"address"}],"name":"addCToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract ICompoundToken[]","name":"cTokens","type":"address[]"}],"name":"addCTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"cTokenByToken","outputs":[{"internalType":"contract ICompoundToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"contract ICompoundToken","name":"cToken","type":"address"}],"name":"tokenByCToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /CompoundRegistry.full.bin: -------------------------------------------------------------------------------- 1 | 608060405260006100176001600160e01b0361006616565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006a565b3390565b610681806100796000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b1461016f5780638f32d59b146101775780639bbde94714610193578063f2fde38b146101b957610088565b80631d2493541461008d57806332a5d5bf146100ff5780633842805c14610141578063715018a614610167575b600080fd5b6100fd600480360360208110156100a357600080fd5b8101906020810181356401000000008111156100be57600080fd5b8201836020820111156100d057600080fd5b803590602001918460208302840111640100000000831117156100f257600080fd5b5090925090506101df565b005b6101256004803603602081101561011557600080fd5b50356001600160a01b0316610262565b604080516001600160a01b039092168252519081900360200190f35b6100fd6004803603602081101561015757600080fd5b50356001600160a01b03166102b8565b6100fd6103b0565b610125610441565b61017f610450565b604080519115158252519081900360200190f35b610125600480360360208110156101a957600080fd5b50356001600160a01b0316610474565b6100fd600480360360208110156101cf57600080fd5b50356001600160a01b03166104d5565b6101e7610450565b610226576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b60005b8181101561025d5761025583838381811061024057fe5b905060200201356001600160a01b03166102b8565b600101610229565b505050565b6000610276826001600160a01b0316610528565b156102965750734ddc2d193948926d02f9b1fe9e1daa0718270ed56102b3565b506001600160a01b03808216600090815260026020526040902054165b919050565b6102c0610450565b6102ff576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b6000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561033a57600080fd5b505afa15801561034e573d6000803e3d6000fd5b505050506040513d602081101561036457600080fd5b50516001600160a01b0392831660008181526001602090815260408083208054979095166001600160a01b03199788168117909555938252600290529190912080549093161790915550565b6103b8610450565b6103f7576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b600080546001600160a01b0316610465610562565b6001600160a01b031614905090565b60006001600160a01b038216734ddc2d193948926d02f9b1fe9e1daa0718270ed514156104b6575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6102b3565b506001600160a01b039081166000908152600160205260409020541690565b6104dd610450565b61051c576040805162461bcd60e51b8152602060048201819052602482015260008051602061062d833981519152604482015290519081900360640190fd5b61052581610566565b50565b60006001600160a01b038216158061055c57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b3390565b6001600160a01b0381166105ab5760405162461bcd60e51b81526004018080602001828103825260268152602001806106076026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a265627a7a72315820f98c5c6f5735da117d41870c8dbcd834d42b2c7d374cfd246c8f2ec756462f6864736f6c63430005110032 -------------------------------------------------------------------------------- /KyberReserves.md: -------------------------------------------------------------------------------- 1 | # Kyber Reserves 2 | 3 | There are 3 different 1-byte prefixes of reserve id: 4 | - `0xAA` for [Automated Price Reserve](https://developer.kyber.network/docs/Reserves-AutomatedPriceReserve/) 5 | - `0xFF` for [Fed Price Reserve](https://developer.kyber.network/docs/Reserves-FedPriceReserve/) 6 | - `0xBB` for Bridged Price Reserves 7 | 8 | ## Multiple token reserves 9 | 10 | | Name | Address | Reserve ID | 11 | | ---- | ---- | ---- | 12 | | Reserve 1 | [`0x63825c174ab367968EC60f061753D3bbD36A0D8F`](https://etherscan.io/address/0x63825c174ab367968EC60f061753D3bbD36A0D8F) | `0xff4b796265722046707200000000000000000000000000000000000000000000` | 13 | | Reserve 2 | [`0x7a3370075a54B187d7bD5DceBf0ff2B5552d4F7D`](https://etherscan.io/address/0x7a3370075a54B187d7bD5DceBf0ff2B5552d4F7D) | `0xffabcd0000000000000000000000000000000000000000000000000000000000` | 14 | | Reserve 3 | [`0x4f32BbE8dFc9efD54345Fc936f9fEF1048746fCF`](https://etherscan.io/address/0x4f32BbE8dFc9efD54345Fc936f9fEF1048746fCF) | `0xff4f6e65426974205175616e7400000000000000000000000000000000000000` | 15 | 16 | ## Bridged Reserves 17 | 18 | | Name | Address | Reserve ID | 19 | | ---- | ---- | ---- | 20 | | Oasis (Eth2Dai) | [`0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f`](https://etherscan.io/address/0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f) | `0xbb4f617369730000000000000000000000000000000000000000000000000000` | 21 | | Uniswap | [`0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F`](https://etherscan.io/address/0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F) | `0xbb756e6973776170563100000000000000000000000000000000000000000000` | 22 | | Uniswap V2 | [`0x10908C875D865C66f271F5d3949848971c9595C9`](https://etherscan.io/address/0x10908C875D865C66f271F5d3949848971c9595C9) | `0xbb756e6973776170563200000000000000000000000000000000000000000000` | 23 | | Bancor | [`0x1fE867bFE9cbE0045467605B959A355223E3885D`](https://etherscan.io/address/0x1fE867bFE9cbE0045467605B959A355223E3885D)| `0xbb42414e434f5230305632000000000000000000000000000000000000000000` | 24 | 25 | 26 | ## Single token reserves 27 | 28 | | Name | Address | Reserve ID | 29 | | ---- | ---- | ---- | 30 | | [ABYSS](https://etherscan.io/address/0x0E8d6b471e332F140e7d9dbB99E5E3822F728DA6) | [`0x3e9FFBA3C3eB91f501817b031031a71de2d3163B`](https://etherscan.io/address/0x3e9FFBA3C3eB91f501817b031031a71de2d3163B) | `0xaa41627973730000000000000000000000000000000000000000000000000000` | 31 | | [EQUAD](https://etherscan.io/address/0xC28e931814725BbEB9e670676FaBBCb694Fe7DF2) | [`0x0232Ba609782Cea145Ec3663F52CF7aEb4AC773C`](https://etherscan.io/address/0x0232Ba609782Cea145Ec3663F52CF7aEb4AC773C) | `0xaa65515541440000000000000000000000000000000000000000000000000000` | 32 | | [MLN](https://etherscan.io/address/0xec67005c4E498Ec7f55E092bd1d35cbC47C91892) | [`0xa33c7c22d0BB673c2aEa2C048BB883b679fa1BE9`](https://etherscan.io/address/0xa33c7c22d0BB673c2aEa2C048BB883b679fa1BE9) | `0xaa4d656c6f6e706f727400000000000000000000000000000000000000000000` | 33 | | [REN](https://etherscan.io/address/0x408e41876cCCDC0F92210600ef50372656052a38) | [`0x45eb33D008801d547990cAF3b63B4F8aE596EA57`](https://etherscan.io/address/0x45eb33D008801d547990cAF3b63B4F8aE596EA57) | `0xaa72656e00000000000000000000000000000000000000000000000000000000` | 34 | | [USDC](https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) | [`0x1670DFb52806DE7789D5cF7D5c005cf7083f9A5D`](https://etherscan.io/address/0x1670DFb52806DE7789D5cF7D5c005cf7083f9A5D) | `0xaa55534443303041505200000000000000000000000000000000000000000000` | 35 | | [GEN](https://etherscan.io/address/0x543Ff227F64Aa17eA132Bf9886cAb5DB55DCAddf) | [`0xAA14DCAA0AdbE79cBF00edC6cC4ED17ed39240AC`](https://etherscan.io/address/0xAA14DCAA0AdbE79cBF00edC6cC4ED17ed39240AC) | `0xaa47454e00000000000000000000000000000000000000000000000000000000` | 36 | | [GNO](https://etherscan.io/address/0x6810e776880C02933D47DB1b9fc05908e5386b96) | [`0x05461124C86C0AD7C5d8E012e1499fd9109fFb7d`](https://etherscan.io/address/0x05461124C86C0AD7C5d8E012e1499fd9109fFb7d) | `0xaa4b4e4320474e4f000000000000000000000000000000000000000000000000` | 37 | | [MYB](https://etherscan.io/address/0x5d60d8d7eF6d37E16EBABc324de3bE57f135e0BC) | [`0x1833AD67362249823515B59A8aA8b4f6B4358d1B`](https://etherscan.io/address/0x1833AD67362249823515B59A8aA8b4f6B4358d1B) | `0xaa4d594200000000000000000000000000000000000000000000000000000000` | 38 | | [BAM](https://etherscan.io/address/0x22B3FAaa8DF978F6bAFe18aaDe18DC2e3dfA0e0C) | [`0x302B35bd0B01312ec2652783c04955D7200C3D9b`](https://etherscan.io/address/0x302B35bd0B01312ec2652783c04955D7200C3D9b) | `0xaa42414d00000000000000000000000000000000000000000000000000000000` | 39 | | [SPN](https://etherscan.io/address/0x20F7A3DdF244dc9299975b4Da1C39F8D5D75f05A) | [`0x6b84DBd29643294703dBabf8Ed97cDef74EDD227`](https://etherscan.io/address/0x6b84DBd29643294703dBabf8Ed97cDef74EDD227) | `0xaa48756d616e7320466972737400000000000000000000000000000000000000` | 40 | | [UPP](https://etherscan.io/address/0xC86D054809623432210c107af2e3F619DcFbf652) | [`0x7e2fd015616263Add31a2AcC2A437557cEe80Fc4`](https://etherscan.io/address/0x7e2fd015616263Add31a2AcC2A437557cEe80Fc4) | `0xaa55505000000000000000000000000000000000000000000000000000000000` | 41 | | [SNX](https://etherscan.io/address/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F) | [`0xa107dfa919c3f084a7893A260b99586981beb528`](https://etherscan.io/address/0xa107dfa919c3f084a7893A260b99586981beb528) | `0xaa534e5800000000000000000000000000000000000000000000000000000000` | 42 | | [TKN](https://etherscan.io/address/0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a) | [`0x3480E12B6C2438e02319e34b4c23770679169190`](https://etherscan.io/address/0x3480E12B6C2438e02319e34b4c23770679169190) | `0xaa97aad58d5670d74ffb37e8c6272b3463f08be662718f7681c6e5bffc1b05c0` | 43 | | [RAE](https://etherscan.io/address/0xE5a3229CCb22b6484594973A03a3851dCd948756) | [`0x751Eea622edd1E3D768C18afbCaeC7DcE7750C65`](https://etherscan.io/address/0x751Eea622edd1E3D768C18afbCaeC7DcE7750C65) | `0xaa52414520415052000000000000000000000000000000000000000000000000` | 44 | | [SUSD](https://etherscan.io/address/0x57Ab1ec28D129707052df4dF418D58a2D46d5f51) | [`0x4Cb01bd05E4652CbB9F312aE604f4549D2bf2C99`](https://etherscan.io/address/0x4Cb01bd05E4652CbB9F312aE604f4549D2bf2C99) | `0xaa73555344000000000000000000000000000000000000000000000000000000` | 45 | | [SPIKE](https://etherscan.io/address/0xA7fC5D2453E3F68aF0cc1B78bcFEe94A1B293650) | [`0x8ea5CF9f61824E8A3cA8AA370AB37e0202B2CC7D`](https://etherscan.io/address/0x8ea5CF9f61824E8A3cA8AA370AB37e0202B2CC7D) | `0xaa88888888888888888888888888888888888888888888888888888888888888` | 46 | | [SAN](https://etherscan.io/address/0x7C5A0CE9267ED19B22F8cae653F198e3E8daf098) | [`0xa9742Ee9a5407f4C2f8a49f65E3a440f3694960a`](https://etherscan.io/address/0xa9742Ee9a5407f4C2f8a49f65E3a440f3694960a) | `0xaa53414e20415052000000000000000000000000000000000000000000000000` | 47 | | [KNC](https://etherscan.io/address/0xdd974D5C2e2928deA5F71b9825b8b646686BD200) | [`0x607d7751d9F4845C5a1dE9eeD39c56f4fC0F855d`](https://etherscan.io/address/0x607d7751d9F4845C5a1dE9eeD39c56f4fC0F855d) | `0xaa4b4e435f4d4547414c41444f4e000000000000000000000000000000000000` | 48 | | [EKG](https://etherscan.io/address/0x6A9b3E36436B7abde8C4E2E2a98Ea40455E615cf) | [`0x4e6d0F492fd139151DE4728caC47dAce56C56Af4`](https://etherscan.io/address/0x4e6d0F492fd139151DE4728caC47dAce56C56Af4) | `0xff454b4700000000000000000000000000000000000000000000000000000000` | 49 | | [ANT](https://etherscan.io/address/0x960b236A07cf122663c4303350609A66A7B288C0) | [`0x0994c18Ed0C328F38d2C451B2a2e1cEb1Ae6A812`](https://etherscan.io/address/0x0994c18Ed0C328F38d2C451B2a2e1cEb1Ae6A812) | `0xaa414e5400000000000000000000000000000000000000000000000000000000` | 50 | | [GDC](https://etherscan.io/address/0x301C755bA0fcA00B1923768Fffb3Df7f4E63aF31) | [`0x2485a4e3Dd95a3Ef445B786acf7bacc5C99986F7`](https://etherscan.io/address/0x2485a4e3Dd95a3Ef445B786acf7bacc5C99986F7) | `0xaa676463746f6b656e0000000000000000000000000000000000000000000000` | 51 | | [AMPL](https://etherscan.io/address/0xD46bA6D942050d489DBd938a2C909A5d5039A161) | [`0x977c9ABB01Ed3E99e9953fD1F472aE9f459E7E70`](https://etherscan.io/address/0x977c9ABB01Ed3E99e9953fD1F472aE9f459E7E70) | `0xaad46ba6d942050d489dbd938a2c909a5d5039a1610000000000000000000000` | 52 | | [MET](https://etherscan.io/address/0xa3d58c4E56fedCae3a7c43A725aeE9A71F0ece4e) | [`0x2Ed6F2bC006DA5897A0C3cD2686283C05e50C573`](https://etherscan.io/address/0x2Ed6F2bC006DA5897A0C3cD2686283C05e50C573) | `0xaa4d455400000000000000000000000000000000000000000000000000000000` | 53 | | [MFG](https://etherscan.io/address/0x6710c63432A2De02954fc0f851db07146a6c0312) | [`0x55a8fda671a257b80258d2a03abd6e0e1e3dbe79`](https://etherscan.io/address/0x55a8fda671a257b80258d2a03abd6e0e1e3dbe79) | `0xaa6d6667546f6b656e0000000000000000000000000000000000000000000000` | 54 | | [UBT](https://etherscan.io/address/0x8400D94A5cb0fa0D041a3788e395285d61c9ee5e) | [`0xfe06bc8BC12595C1c871fF7c2ea9CadC42735d7D`](https://etherscan.io/address/0xfe06bc8BC12595C1c871fF7c2ea9CadC42735d7D) | `0xaa55425400000000000000000000000000000000000000000000000000000000` | 55 | | [PBTC](https://etherscan.io/address/0x5228a22e72ccC52d415EcFd199F99D0665E7733b) | [`0x0Ce59E811024C4aA040389fb8917dD9EDAEf1693`](https://etherscan.io/address/0x0Ce59E811024C4aA040389fb8917dD9EDAEf1693) | `0xff50425443000000000000000000000000000000000000000000000000000000` | 56 | | [OGN](https://etherscan.io/address/0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26) | [`0xb89f41CD2C8B6cba8b851289198b06Be8B4Dec65`](https://etherscan.io/address/0xb89f41CD2C8B6cba8b851289198b06Be8B4Dec65) | `0xaa4f474e00000000000000000000000000000000000000000000000000000000` | 57 | | [BAND](https://etherscan.io/address/0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55) | [`0xb06Cf173DA7E297aa6268139c7Cb67C53D8E4f90`](https://etherscan.io/address/0xb06Cf173DA7E297aa6268139c7Cb67C53D8E4f90) | `0xaa42414e44000000000000000000000000000000000000000000000000000000` | 58 | | [RSV](https://etherscan.io/address/0x1C5857e110CD8411054660F60B5De6a6958CfAE2) | [`0x141104687b51985D6210Eb4b398F1DC5b5b9e9F5`](https://etherscan.io/address/0x141104687b51985D6210Eb4b398F1DC5b5b9e9F5) | `0xaa525356546f6b656e0000000000000000000000000000000000000000000000` | 59 | | [KEY](https://etherscan.io/address/0x4CC19356f2D37338b9802aa8E8fc58B0373296E7) | [`0x3e59c69952a4cFEaF653EedF8ff907D4b6b8762D`](https://etherscan.io/address/0x3e59c69952a4cFEaF653EedF8ff907D4b6b8762D) | `0xaa4b455900000000000000000000000000000000000000000000000000000000` | 60 | | [PNK](https://etherscan.io/address/0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d) | [`0x10db2A136ee3E0C963d82aF4C86Ca483199f2816`](https://etherscan.io/address/0x10db2A136ee3E0C963d82aF4C86Ca483199f2816) | `0xaa504e4b00000000000000000000000000000000000000000000000000000000` | 61 | | [CND](https://etherscan.io/address/0xd4c435F5B09F855C3317c8524Cb1F586E42795fa) | [`0xAD84a44a673Be4FdcD5e39Ebd15eBC404E87F314`](https://etherscan.io/address/0xAD84a44a673Be4FdcD5e39Ebd15eBC404E87F314) | `0xaa434e4400000000000000000000000000000000000000000000000000000000` | 62 | | [TRYB](https://etherscan.io/address/0x2C537E5624e4af88A7ae4060C022609376C8D0EB) | [`0xe96b41aF3DA574A991582dC54cC35535550a3f8d`](https://etherscan.io/address/0xe96b41aF3DA574A991582dC54cC35535550a3f8d) | `0xaa54525942000000000000000000000000000000000000000000000000000000` | 63 | | [2KEY](https://etherscan.io/address/0xE48972fCd82a274411c01834e2f031D4377Fa2c0) | [`0x00Cd2388C86C960A646D640bE44FC8F83b78cEC9`](https://etherscan.io/address/0x00Cd2388C86C960A646D640bE44FC8F83b78cEC9) | `0xaacfefe57c1e0f781f9864fe27287980a2097e60c0ee0c5e71083e32cecd1c9c` | 64 | | [PLR](https://etherscan.io/address/0xe3818504c1B32bF1557b16C238B2E01Fd3149C17) | [`0x71eb6edF770b25Fcd60Ad9790AA20C422F0f4a0d`](https://etherscan.io/address/0x71eb6edF770b25Fcd60Ad9790AA20C422F0f4a0d) | `0xaa504c5200000000000000000000000000000000000000000000000000000000` | 65 | | [QNT](https://etherscan.io/address/0x4a220E6096B25EADb88358cb44068A3248254675) | [`0x773A58C0ae122f56d6747BC1264F00174B3144c3`](https://etherscan.io/address/0x773A58C0ae122f56d6747BC1264F00174B3144c3) | `0xaa514e5452657365727665000000000000000000000000000000000000000000` | 66 | | [PNT](https://etherscan.io/address/0x89Ab32156e46F46D02ade3FEcbe5Fc4243B9AAeD) | [`0x89b3F60A17789Aa7c7061Af6f5e9efA407153C03`](https://etherscan.io/address/0x89b3F60A17789Aa7c7061Af6f5e9efA407153C03) | `0xff504e5400000000000000000000000000000000000000000000000000000000` | 67 | | [REQ](https://etherscan.io/address/0x8f8221aFbB33998d8584A2B05749bA73c37a938a) | [`0x23Fe3C603BE19d3a1155766358071CAcEFe14537`](https://etherscan.io/address/0x23Fe3C603BE19d3a1155766358071CAcEFe14537) | `0xaa52455100000000000000000000000000000000000000000000000000000000` | 68 | | [RSR](https://etherscan.io/address/0x8762db106B2c2A0bccB3A80d1Ed41273552616E8) | [`0x0b798B89155eA31f1312791b9fdFAae7c5F48460`](https://etherscan.io/address/0x0b798B89155eA31f1312791b9fdFAae7c5F48460) | `0xaa525352546f6b656e0000000000000000000000000000000000000000000000` | 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 CryptoManiacs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /OneSplit.full.abi: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"contract IOneSplitView","name":"_oneSplitView","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"},{"internalType":"uint256","name":"destTokenEthPriceTimesGasPrice","type":"uint256"}],"name":"getExpectedReturnWithGas","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256","name":"estimateGasAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oneSplitView","outputs":[{"internalType":"contract IOneSplitView","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"}] -------------------------------------------------------------------------------- /OneSplitAudit.full.abi: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"contract IOneSplitMulti","name":"impl","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newImpl","type":"address"}],"name":"ImplementationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"fromToken","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minReturn","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"indexed":false,"internalType":"address","name":"referral","type":"address"},{"indexed":false,"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"Swapped","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"chi","outputs":[{"internalType":"contract IFreeFromUpTo","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"},{"internalType":"uint256","name":"destTokenEthPriceTimesGasPrice","type":"uint256"}],"name":"getExpectedReturnWithGas","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256","name":"estimateGasAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"parts","type":"uint256[]"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"internalType":"uint256[]","name":"destTokenEthPriceTimesGasPrices","type":"uint256[]"}],"name":"getExpectedReturnWithGasMulti","outputs":[{"internalType":"uint256[]","name":"returnAmounts","type":"uint256[]"},{"internalType":"uint256","name":"estimateGasAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oneSplitImpl","outputs":[{"internalType":"contract IOneSplitMulti","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IOneSplitMulti","name":"impl","type":"address"}],"name":"setNewImpl","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"}],"name":"swapMulti","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"},{"internalType":"address","name":"referral","type":"address"},{"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"swapWithReferral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256[]","name":"flags","type":"uint256[]"},{"internalType":"address","name":"referral","type":"address"},{"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"swapWithReferralMulti","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /OneSplitView.full.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"DEXES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"},{"internalType":"uint256","name":"toTokenEthPrice","type":"uint256"}],"name":"getExpectedReturnRespectingGas","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256","name":"estimateGasAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"log","outputs":[],"payable":false,"stateMutability":"view","type":"function"}] -------------------------------------------------------------------------------- /contracts/1inchProtocol-audit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1inch/1inchProtocol/811f7b69b67d1d9657e3e9c18a2e97f3e2b2b33a/contracts/1inchProtocol-audit.pdf -------------------------------------------------------------------------------- /contracts/AaveRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./interface/IAaveRegistry.sol"; 6 | import "./UniversalERC20.sol"; 7 | 8 | 9 | contract AaveRegistry is Ownable, IAaveRegistry { 10 | using UniversalERC20 for IERC20; 11 | 12 | IAaveToken internal constant aETH = IAaveToken(0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04); 13 | IERC20 internal constant ETH = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); 14 | 15 | mapping(address => address) private _tokenByAToken; 16 | mapping(address => address) private _aTokenByToken; 17 | 18 | function tokenByAToken(IAaveToken aToken) external view returns(IERC20) { 19 | if (aToken == aETH) { 20 | return ETH; 21 | } 22 | return IERC20(_tokenByAToken[address(aToken)]); 23 | } 24 | 25 | function aTokenByToken(IERC20 token) external view returns(IAaveToken) { 26 | if (token.isETH()) { 27 | return aETH; 28 | } 29 | return IAaveToken(_aTokenByToken[address(token)]); 30 | } 31 | 32 | function addAToken(IAaveToken aToken) public onlyOwner { 33 | IERC20 token = IERC20(aToken.underlyingAssetAddress()); 34 | _tokenByAToken[address(aToken)] = address(token); 35 | _aTokenByToken[address(token)] = address(aToken); 36 | } 37 | 38 | function addATokens(IAaveToken[] calldata cTokens) external onlyOwner { 39 | for (uint i = 0; i < cTokens.length; i++) { 40 | addAToken(cTokens[i]); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/BalancerHelper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./interface/IBalancerPool.sol"; 6 | import "./BalancerLib.sol"; 7 | 8 | 9 | contract BalancerHelper { 10 | using SafeMath for uint256; 11 | 12 | function getReturns( 13 | IBalancerPool pool, 14 | IERC20 fromToken, 15 | IERC20 destToken, 16 | uint256[] calldata amounts 17 | ) 18 | external 19 | view 20 | returns(uint256[] memory rets) 21 | { 22 | uint256 swapFee = pool.getSwapFee(); 23 | uint256 fromBalance = pool.getBalance(fromToken); 24 | uint256 destBalance = pool.getBalance(destToken); 25 | uint256 fromWeight = pool.getDenormalizedWeight(fromToken); 26 | uint256 destWeight = pool.getDenormalizedWeight(destToken); 27 | 28 | rets = new uint256[](amounts.length); 29 | for (uint i = 0; i < amounts.length && amounts[i].mul(2) <= fromBalance; i++) { 30 | rets[i] = BalancerLib.calcOutGivenIn( 31 | fromBalance, 32 | fromWeight, 33 | destBalance, 34 | destWeight, 35 | amounts[i], 36 | swapFee 37 | ); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/BancorFinder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "./interface/IBancorContractRegistry.sol"; 5 | import "./interface/IBancorConverterRegistry.sol"; 6 | import "./UniversalERC20.sol"; 7 | 8 | 9 | contract BancorFinder { 10 | using UniversalERC20 for IERC20; 11 | 12 | IERC20 constant internal ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); 13 | IERC20 constant internal bnt = IERC20(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C); 14 | IBancorContractRegistry constant internal bancorContractRegistry = IBancorContractRegistry(0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4); 15 | 16 | function buildBancorPath( 17 | IERC20 fromToken, 18 | IERC20 destToken 19 | ) 20 | public 21 | view 22 | returns(address[] memory path) 23 | { 24 | if (fromToken == destToken) { 25 | return new address[](0); 26 | } 27 | 28 | if (fromToken.isETH()) { 29 | fromToken = ETH_ADDRESS; 30 | } 31 | if (destToken.isETH()) { 32 | destToken = ETH_ADDRESS; 33 | } 34 | 35 | if (fromToken == bnt || destToken == bnt) { 36 | path = new address[](3); 37 | } else { 38 | path = new address[](5); 39 | } 40 | 41 | address fromConverter; 42 | address toConverter; 43 | 44 | IBancorConverterRegistry bancorConverterRegistry = IBancorConverterRegistry( 45 | bancorContractRegistry.addressOf("BancorConverterRegistry") 46 | ); 47 | 48 | if (fromToken != bnt) { 49 | (bool success, bytes memory data) = address(bancorConverterRegistry).staticcall.gas(100000)(abi.encodeWithSelector( 50 | bancorConverterRegistry.getConvertibleTokenSmartToken.selector, 51 | fromToken.isETH() ? ETH_ADDRESS : fromToken, 52 | 0 53 | )); 54 | if (!success) { 55 | return new address[](0); 56 | } 57 | 58 | fromConverter = abi.decode(data, (address)); 59 | if (fromConverter == address(0)) { 60 | return new address[](0); 61 | } 62 | } 63 | 64 | if (destToken != bnt) { 65 | (bool success, bytes memory data) = address(bancorConverterRegistry).staticcall.gas(100000)(abi.encodeWithSelector( 66 | bancorConverterRegistry.getConvertibleTokenSmartToken.selector, 67 | destToken.isETH() ? ETH_ADDRESS : destToken, 68 | 0 69 | )); 70 | if (!success) { 71 | return new address[](0); 72 | } 73 | 74 | toConverter = abi.decode(data, (address)); 75 | if (toConverter == address(0)) { 76 | return new address[](0); 77 | } 78 | } 79 | 80 | if (destToken == bnt) { 81 | path[0] = address(fromToken); 82 | path[1] = fromConverter; 83 | path[2] = address(bnt); 84 | return path; 85 | } 86 | 87 | if (fromToken == bnt) { 88 | path[0] = address(bnt); 89 | path[1] = toConverter; 90 | path[2] = address(destToken); 91 | return path; 92 | } 93 | 94 | path[0] = address(fromToken); 95 | path[1] = fromConverter; 96 | path[2] = address(bnt); 97 | path[3] = toConverter; 98 | path[4] = address(destToken); 99 | return path; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /contracts/CompoundRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./interface/ICompoundRegistry.sol"; 6 | import "./UniversalERC20.sol"; 7 | 8 | 9 | contract CompoundRegistry is Ownable, ICompoundRegistry { 10 | using UniversalERC20 for IERC20; 11 | 12 | ICompoundToken internal constant cETH = ICompoundToken(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5); 13 | IERC20 internal constant ETH = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); 14 | 15 | mapping(address => address) private _tokenByCToken; 16 | mapping(address => address) private _cTokenByToken; 17 | 18 | function tokenByCToken(ICompoundToken cToken) external view returns(IERC20) { 19 | if (cToken == cETH) { 20 | return ETH; 21 | } 22 | return IERC20(_tokenByCToken[address(cToken)]); 23 | } 24 | 25 | function cTokenByToken(IERC20 token) external view returns(ICompoundToken) { 26 | if (token.isETH()) { 27 | return cETH; 28 | } 29 | return ICompoundToken(_cTokenByToken[address(token)]); 30 | } 31 | 32 | function addCToken(ICompoundToken cToken) public onlyOwner { 33 | IERC20 token = IERC20(cToken.underlying()); 34 | _tokenByCToken[address(cToken)] = address(token); 35 | _cTokenByToken[address(token)] = address(cToken); 36 | } 37 | 38 | function addCTokens(ICompoundToken[] calldata cTokens) external onlyOwner { 39 | for (uint i = 0; i < cTokens.length; i++) { 40 | addCToken(cTokens[i]); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/IOneSplit.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | // 6 | // [ msg.sender ] 7 | // | | 8 | // | | 9 | // \_/ 10 | // +---------------+ ________________________________ 11 | // | OneSplitAudit | _______________________________ \ 12 | // +---------------+ \ \ 13 | // | | ______________ | | (staticcall) 14 | // | | / ____________ \ | | 15 | // | | (call) / / \ \ | | 16 | // | | / / | | | | 17 | // \_/ | | \_/ \_/ 18 | // +--------------+ | | +----------------------+ 19 | // | OneSplitWrap | | | | OneSplitViewWrap | 20 | // +--------------+ | | +----------------------+ 21 | // | | | | | | 22 | // | | (delegatecall) | | (staticcall) | | (staticcall) 23 | // \_/ | | \_/ 24 | // +--------------+ | | +------------------+ 25 | // | OneSplit | | | | OneSplitView | 26 | // +--------------+ | | +------------------+ 27 | // | | / / 28 | // \ \________________/ / 29 | // \__________________/ 30 | // 31 | 32 | 33 | contract IOneSplitConsts { 34 | // flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_BANCOR + ... 35 | uint256 internal constant FLAG_DISABLE_UNISWAP = 0x01; 36 | uint256 internal constant DEPRECATED_FLAG_DISABLE_KYBER = 0x02; // Deprecated 37 | uint256 internal constant FLAG_DISABLE_BANCOR = 0x04; 38 | uint256 internal constant FLAG_DISABLE_OASIS = 0x08; 39 | uint256 internal constant FLAG_DISABLE_COMPOUND = 0x10; 40 | uint256 internal constant FLAG_DISABLE_FULCRUM = 0x20; 41 | uint256 internal constant FLAG_DISABLE_CHAI = 0x40; 42 | uint256 internal constant FLAG_DISABLE_AAVE = 0x80; 43 | uint256 internal constant FLAG_DISABLE_SMART_TOKEN = 0x100; 44 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_ETH = 0x200; // Deprecated, Turned off by default 45 | uint256 internal constant FLAG_DISABLE_BDAI = 0x400; 46 | uint256 internal constant FLAG_DISABLE_IEARN = 0x800; 47 | uint256 internal constant FLAG_DISABLE_CURVE_COMPOUND = 0x1000; 48 | uint256 internal constant FLAG_DISABLE_CURVE_USDT = 0x2000; 49 | uint256 internal constant FLAG_DISABLE_CURVE_Y = 0x4000; 50 | uint256 internal constant FLAG_DISABLE_CURVE_BINANCE = 0x8000; 51 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_DAI = 0x10000; // Deprecated, Turned off by default 52 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_USDC = 0x20000; // Deprecated, Turned off by default 53 | uint256 internal constant FLAG_DISABLE_CURVE_SYNTHETIX = 0x40000; 54 | uint256 internal constant FLAG_DISABLE_WETH = 0x80000; 55 | uint256 internal constant FLAG_DISABLE_UNISWAP_COMPOUND = 0x100000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH 56 | uint256 internal constant FLAG_DISABLE_UNISWAP_CHAI = 0x200000; // Works only when ETH<>DAI or FLAG_ENABLE_MULTI_PATH_ETH 57 | uint256 internal constant FLAG_DISABLE_UNISWAP_AAVE = 0x400000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH 58 | uint256 internal constant FLAG_DISABLE_IDLE = 0x800000; 59 | uint256 internal constant FLAG_DISABLE_MOONISWAP = 0x1000000; 60 | uint256 internal constant FLAG_DISABLE_UNISWAP_V2 = 0x2000000; 61 | uint256 internal constant FLAG_DISABLE_UNISWAP_V2_ETH = 0x4000000; 62 | uint256 internal constant FLAG_DISABLE_UNISWAP_V2_DAI = 0x8000000; 63 | uint256 internal constant FLAG_DISABLE_UNISWAP_V2_USDC = 0x10000000; 64 | uint256 internal constant FLAG_DISABLE_ALL_SPLIT_SOURCES = 0x20000000; 65 | uint256 internal constant FLAG_DISABLE_ALL_WRAP_SOURCES = 0x40000000; 66 | uint256 internal constant FLAG_DISABLE_CURVE_PAX = 0x80000000; 67 | uint256 internal constant FLAG_DISABLE_CURVE_RENBTC = 0x100000000; 68 | uint256 internal constant FLAG_DISABLE_CURVE_TBTC = 0x200000000; 69 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_USDT = 0x400000000; // Deprecated, Turned off by default 70 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_WBTC = 0x800000000; // Deprecated, Turned off by default 71 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_TBTC = 0x1000000000; // Deprecated, Turned off by default 72 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_RENBTC = 0x2000000000; // Deprecated, Turned off by default 73 | uint256 internal constant FLAG_DISABLE_DFORCE_SWAP = 0x4000000000; 74 | uint256 internal constant FLAG_DISABLE_SHELL = 0x8000000000; 75 | uint256 internal constant FLAG_ENABLE_CHI_BURN = 0x10000000000; 76 | uint256 internal constant FLAG_DISABLE_MSTABLE_MUSD = 0x20000000000; 77 | uint256 internal constant FLAG_DISABLE_CURVE_SBTC = 0x40000000000; 78 | uint256 internal constant FLAG_DISABLE_DMM = 0x80000000000; 79 | uint256 internal constant FLAG_DISABLE_UNISWAP_ALL = 0x100000000000; 80 | uint256 internal constant FLAG_DISABLE_CURVE_ALL = 0x200000000000; 81 | uint256 internal constant FLAG_DISABLE_UNISWAP_V2_ALL = 0x400000000000; 82 | uint256 internal constant FLAG_DISABLE_SPLIT_RECALCULATION = 0x800000000000; 83 | uint256 internal constant FLAG_DISABLE_BALANCER_ALL = 0x1000000000000; 84 | uint256 internal constant FLAG_DISABLE_BALANCER_1 = 0x2000000000000; 85 | uint256 internal constant FLAG_DISABLE_BALANCER_2 = 0x4000000000000; 86 | uint256 internal constant FLAG_DISABLE_BALANCER_3 = 0x8000000000000; 87 | uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_UNISWAP_RESERVE = 0x10000000000000; // Deprecated, Turned off by default 88 | uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_OASIS_RESERVE = 0x20000000000000; // Deprecated, Turned off by default 89 | uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_BANCOR_RESERVE = 0x40000000000000; // Deprecated, Turned off by default 90 | uint256 internal constant FLAG_ENABLE_REFERRAL_GAS_SPONSORSHIP = 0x80000000000000; // Turned off by default 91 | uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_COMP = 0x100000000000000; // Deprecated, Turned off by default 92 | uint256 internal constant FLAG_DISABLE_KYBER_ALL = 0x200000000000000; 93 | uint256 internal constant FLAG_DISABLE_KYBER_1 = 0x400000000000000; 94 | uint256 internal constant FLAG_DISABLE_KYBER_2 = 0x800000000000000; 95 | uint256 internal constant FLAG_DISABLE_KYBER_3 = 0x1000000000000000; 96 | uint256 internal constant FLAG_DISABLE_KYBER_4 = 0x2000000000000000; 97 | uint256 internal constant FLAG_ENABLE_CHI_BURN_BY_ORIGIN = 0x4000000000000000; 98 | uint256 internal constant FLAG_DISABLE_MOONISWAP_ALL = 0x8000000000000000; 99 | uint256 internal constant FLAG_DISABLE_MOONISWAP_ETH = 0x10000000000000000; 100 | uint256 internal constant FLAG_DISABLE_MOONISWAP_DAI = 0x20000000000000000; 101 | uint256 internal constant FLAG_DISABLE_MOONISWAP_USDC = 0x40000000000000000; 102 | uint256 internal constant FLAG_DISABLE_MOONISWAP_POOL_TOKEN = 0x80000000000000000; 103 | } 104 | 105 | 106 | contract IOneSplit is IOneSplitConsts { 107 | function getExpectedReturn( 108 | IERC20 fromToken, 109 | IERC20 destToken, 110 | uint256 amount, 111 | uint256 parts, 112 | uint256 flags // See constants in IOneSplit.sol 113 | ) 114 | public 115 | view 116 | returns( 117 | uint256 returnAmount, 118 | uint256[] memory distribution 119 | ); 120 | 121 | function getExpectedReturnWithGas( 122 | IERC20 fromToken, 123 | IERC20 destToken, 124 | uint256 amount, 125 | uint256 parts, 126 | uint256 flags, // See constants in IOneSplit.sol 127 | uint256 destTokenEthPriceTimesGasPrice 128 | ) 129 | public 130 | view 131 | returns( 132 | uint256 returnAmount, 133 | uint256 estimateGasAmount, 134 | uint256[] memory distribution 135 | ); 136 | 137 | function swap( 138 | IERC20 fromToken, 139 | IERC20 destToken, 140 | uint256 amount, 141 | uint256 minReturn, 142 | uint256[] memory distribution, 143 | uint256 flags 144 | ) 145 | public 146 | payable 147 | returns(uint256 returnAmount); 148 | } 149 | 150 | 151 | contract IOneSplitMulti is IOneSplit { 152 | function getExpectedReturnWithGasMulti( 153 | IERC20[] memory tokens, 154 | uint256 amount, 155 | uint256[] memory parts, 156 | uint256[] memory flags, 157 | uint256[] memory destTokenEthPriceTimesGasPrices 158 | ) 159 | public 160 | view 161 | returns( 162 | uint256[] memory returnAmounts, 163 | uint256 estimateGasAmount, 164 | uint256[] memory distribution 165 | ); 166 | 167 | function swapMulti( 168 | IERC20[] memory tokens, 169 | uint256 amount, 170 | uint256 minReturn, 171 | uint256[] memory distribution, 172 | uint256[] memory flags 173 | ) 174 | public 175 | payable 176 | returns(uint256 returnAmount); 177 | } 178 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | contract Migrations { 5 | address public owner; 6 | uint public lastCompletedMigration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) { 10 | _; 11 | } 12 | } 13 | 14 | constructor() public { 15 | owner = msg.sender; 16 | } 17 | 18 | function setCompleted(uint completed) public restricted { 19 | lastCompletedMigration = completed; 20 | } 21 | 22 | function upgrade(address newAddress) public restricted { 23 | Migrations upgraded = Migrations(newAddress); 24 | upgraded.setCompleted(lastCompletedMigration); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/OneSplit.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IOneSplit.sol"; 4 | import "./OneSplitBase.sol"; 5 | import "./OneSplitCompound.sol"; 6 | import "./OneSplitFulcrum.sol"; 7 | import "./OneSplitChai.sol"; 8 | import "./OneSplitBdai.sol"; 9 | import "./OneSplitIearn.sol"; 10 | import "./OneSplitIdle.sol"; 11 | import "./OneSplitAave.sol"; 12 | import "./OneSplitWeth.sol"; 13 | import "./OneSplitMStable.sol"; 14 | import "./OneSplitDMM.sol"; 15 | import "./OneSplitMooniswapPoolToken.sol"; 16 | 17 | 18 | contract OneSplitViewWrap is 19 | OneSplitViewWrapBase, 20 | OneSplitMStableView, 21 | OneSplitChaiView, 22 | OneSplitBdaiView, 23 | OneSplitAaveView, 24 | OneSplitFulcrumView, 25 | OneSplitCompoundView, 26 | OneSplitIearnView, 27 | OneSplitIdleView, 28 | OneSplitWethView, 29 | OneSplitDMMView, 30 | OneSplitMooniswapTokenView 31 | { 32 | IOneSplitView public oneSplitView; 33 | 34 | constructor(IOneSplitView _oneSplit) public { 35 | oneSplitView = _oneSplit; 36 | } 37 | 38 | function getExpectedReturn( 39 | IERC20 fromToken, 40 | IERC20 destToken, 41 | uint256 amount, 42 | uint256 parts, 43 | uint256 flags 44 | ) 45 | public 46 | view 47 | returns( 48 | uint256 returnAmount, 49 | uint256[] memory distribution 50 | ) 51 | { 52 | (returnAmount, , distribution) = getExpectedReturnWithGas( 53 | fromToken, 54 | destToken, 55 | amount, 56 | parts, 57 | flags, 58 | 0 59 | ); 60 | } 61 | 62 | function getExpectedReturnWithGas( 63 | IERC20 fromToken, 64 | IERC20 destToken, 65 | uint256 amount, 66 | uint256 parts, 67 | uint256 flags, // See constants in IOneSplit.sol 68 | uint256 destTokenEthPriceTimesGasPrice 69 | ) 70 | public 71 | view 72 | returns( 73 | uint256 returnAmount, 74 | uint256 estimateGasAmount, 75 | uint256[] memory distribution 76 | ) 77 | { 78 | if (fromToken == destToken) { 79 | return (amount, 0, new uint256[](DEXES_COUNT)); 80 | } 81 | 82 | return super.getExpectedReturnWithGas( 83 | fromToken, 84 | destToken, 85 | amount, 86 | parts, 87 | flags, 88 | destTokenEthPriceTimesGasPrice 89 | ); 90 | } 91 | 92 | function _getExpectedReturnRespectingGasFloor( 93 | IERC20 fromToken, 94 | IERC20 destToken, 95 | uint256 amount, 96 | uint256 parts, 97 | uint256 flags, 98 | uint256 destTokenEthPriceTimesGasPrice 99 | ) 100 | internal 101 | view 102 | returns( 103 | uint256 returnAmount, 104 | uint256 estimateGasAmount, 105 | uint256[] memory distribution 106 | ) 107 | { 108 | return oneSplitView.getExpectedReturnWithGas( 109 | fromToken, 110 | destToken, 111 | amount, 112 | parts, 113 | flags, 114 | destTokenEthPriceTimesGasPrice 115 | ); 116 | } 117 | } 118 | 119 | 120 | contract OneSplitWrap is 121 | OneSplitBaseWrap, 122 | OneSplitMStable, 123 | OneSplitChai, 124 | OneSplitBdai, 125 | OneSplitAave, 126 | OneSplitFulcrum, 127 | OneSplitCompound, 128 | OneSplitIearn, 129 | OneSplitIdle, 130 | OneSplitWeth, 131 | OneSplitDMM, 132 | OneSplitMooniswapToken 133 | { 134 | IOneSplitView public oneSplitView; 135 | IOneSplit public oneSplit; 136 | 137 | constructor(IOneSplitView _oneSplitView, IOneSplit _oneSplit) public { 138 | oneSplitView = _oneSplitView; 139 | oneSplit = _oneSplit; 140 | } 141 | 142 | function() external payable { 143 | // solium-disable-next-line security/no-tx-origin 144 | require(msg.sender != tx.origin); 145 | } 146 | 147 | function getExpectedReturn( 148 | IERC20 fromToken, 149 | IERC20 destToken, 150 | uint256 amount, 151 | uint256 parts, 152 | uint256 flags 153 | ) 154 | public 155 | view 156 | returns( 157 | uint256 returnAmount, 158 | uint256[] memory distribution 159 | ) 160 | { 161 | (returnAmount, , distribution) = getExpectedReturnWithGas( 162 | fromToken, 163 | destToken, 164 | amount, 165 | parts, 166 | flags, 167 | 0 168 | ); 169 | } 170 | 171 | function getExpectedReturnWithGas( 172 | IERC20 fromToken, 173 | IERC20 destToken, 174 | uint256 amount, 175 | uint256 parts, 176 | uint256 flags, 177 | uint256 destTokenEthPriceTimesGasPrice 178 | ) 179 | public 180 | view 181 | returns( 182 | uint256 returnAmount, 183 | uint256 estimateGasAmount, 184 | uint256[] memory distribution 185 | ) 186 | { 187 | return oneSplitView.getExpectedReturnWithGas( 188 | fromToken, 189 | destToken, 190 | amount, 191 | parts, 192 | flags, 193 | destTokenEthPriceTimesGasPrice 194 | ); 195 | } 196 | 197 | function getExpectedReturnWithGasMulti( 198 | IERC20[] memory tokens, 199 | uint256 amount, 200 | uint256[] memory parts, 201 | uint256[] memory flags, 202 | uint256[] memory destTokenEthPriceTimesGasPrices 203 | ) 204 | public 205 | view 206 | returns( 207 | uint256[] memory returnAmounts, 208 | uint256 estimateGasAmount, 209 | uint256[] memory distribution 210 | ) 211 | { 212 | uint256[] memory dist; 213 | 214 | returnAmounts = new uint256[](tokens.length - 1); 215 | for (uint i = 1; i < tokens.length; i++) { 216 | if (tokens[i - 1] == tokens[i]) { 217 | returnAmounts[i - 1] = (i == 1) ? amount : returnAmounts[i - 2]; 218 | continue; 219 | } 220 | 221 | IERC20[] memory _tokens = tokens; 222 | 223 | ( 224 | returnAmounts[i - 1], 225 | amount, 226 | dist 227 | ) = getExpectedReturnWithGas( 228 | _tokens[i - 1], 229 | _tokens[i], 230 | (i == 1) ? amount : returnAmounts[i - 2], 231 | parts[i - 1], 232 | flags[i - 1], 233 | destTokenEthPriceTimesGasPrices[i - 1] 234 | ); 235 | estimateGasAmount = estimateGasAmount.add(amount); 236 | 237 | if (distribution.length == 0) { 238 | distribution = new uint256[](dist.length); 239 | } 240 | for (uint j = 0; j < distribution.length; j++) { 241 | distribution[j] = distribution[j].add(dist[j] << (8 * (i - 1))); 242 | } 243 | } 244 | } 245 | 246 | function swap( 247 | IERC20 fromToken, 248 | IERC20 destToken, 249 | uint256 amount, 250 | uint256 minReturn, 251 | uint256[] memory distribution, 252 | uint256 flags 253 | ) public payable returns(uint256 returnAmount) { 254 | fromToken.universalTransferFrom(msg.sender, address(this), amount); 255 | uint256 confirmed = fromToken.universalBalanceOf(address(this)); 256 | _swap(fromToken, destToken, confirmed, distribution, flags); 257 | 258 | returnAmount = destToken.universalBalanceOf(address(this)); 259 | require(returnAmount >= minReturn, "OneSplit: actual return amount is less than minReturn"); 260 | destToken.universalTransfer(msg.sender, returnAmount); 261 | fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); 262 | } 263 | 264 | function swapMulti( 265 | IERC20[] memory tokens, 266 | uint256 amount, 267 | uint256 minReturn, 268 | uint256[] memory distribution, 269 | uint256[] memory flags 270 | ) public payable returns(uint256 returnAmount) { 271 | tokens[0].universalTransferFrom(msg.sender, address(this), amount); 272 | 273 | returnAmount = tokens[0].universalBalanceOf(address(this)); 274 | for (uint i = 1; i < tokens.length; i++) { 275 | if (tokens[i - 1] == tokens[i]) { 276 | continue; 277 | } 278 | 279 | uint256[] memory dist = new uint256[](distribution.length); 280 | for (uint j = 0; j < distribution.length; j++) { 281 | dist[j] = (distribution[j] >> (8 * (i - 1))) & 0xFF; 282 | } 283 | 284 | _swap( 285 | tokens[i - 1], 286 | tokens[i], 287 | returnAmount, 288 | dist, 289 | flags[i - 1] 290 | ); 291 | returnAmount = tokens[i].universalBalanceOf(address(this)); 292 | tokens[i - 1].universalTransfer(msg.sender, tokens[i - 1].universalBalanceOf(address(this))); 293 | } 294 | 295 | require(returnAmount >= minReturn, "OneSplit: actual return amount is less than minReturn"); 296 | tokens[tokens.length - 1].universalTransfer(msg.sender, returnAmount); 297 | } 298 | 299 | function _swapFloor( 300 | IERC20 fromToken, 301 | IERC20 destToken, 302 | uint256 amount, 303 | uint256[] memory distribution, 304 | uint256 flags 305 | ) internal { 306 | fromToken.universalApprove(address(oneSplit), amount); 307 | oneSplit.swap.value(fromToken.isETH() ? amount : 0)( 308 | fromToken, 309 | destToken, 310 | amount, 311 | 0, 312 | distribution, 313 | flags 314 | ); 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /contracts/OneSplitAave.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IAaveToken.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitAaveView is OneSplitViewWrapBase { 8 | function getExpectedReturnWithGas( 9 | IERC20 fromToken, 10 | IERC20 destToken, 11 | uint256 amount, 12 | uint256 parts, 13 | uint256 flags, // See constants in IOneSplit.sol 14 | uint256 destTokenEthPriceTimesGasPrice 15 | ) 16 | public 17 | view 18 | returns( 19 | uint256 returnAmount, 20 | uint256 estimateGasAmount, 21 | uint256[] memory distribution 22 | ) 23 | { 24 | return _aaveGetExpectedReturn( 25 | fromToken, 26 | destToken, 27 | amount, 28 | parts, 29 | flags, 30 | destTokenEthPriceTimesGasPrice 31 | ); 32 | } 33 | 34 | function _aaveGetExpectedReturn( 35 | IERC20 fromToken, 36 | IERC20 destToken, 37 | uint256 amount, 38 | uint256 parts, 39 | uint256 flags, 40 | uint256 destTokenEthPriceTimesGasPrice 41 | ) 42 | private 43 | view 44 | returns( 45 | uint256 returnAmount, 46 | uint256 estimateGasAmount, 47 | uint256[] memory distribution 48 | ) 49 | { 50 | if (fromToken == destToken) { 51 | return (amount, 0, new uint256[](DEXES_COUNT)); 52 | } 53 | 54 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_AAVE)) { 55 | IERC20 underlying = aaveRegistry.tokenByAToken(IAaveToken(address(fromToken))); 56 | if (underlying != IERC20(0)) { 57 | (returnAmount, estimateGasAmount, distribution) = _aaveGetExpectedReturn( 58 | underlying, 59 | destToken, 60 | amount, 61 | parts, 62 | flags, 63 | destTokenEthPriceTimesGasPrice 64 | ); 65 | return (returnAmount, estimateGasAmount + 670_000, distribution); 66 | } 67 | 68 | underlying = aaveRegistry.tokenByAToken(IAaveToken(address(destToken))); 69 | if (underlying != IERC20(0)) { 70 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 71 | fromToken, 72 | underlying, 73 | amount, 74 | parts, 75 | flags, 76 | destTokenEthPriceTimesGasPrice 77 | ); 78 | return (returnAmount, estimateGasAmount + 310_000, distribution); 79 | } 80 | } 81 | 82 | return super.getExpectedReturnWithGas( 83 | fromToken, 84 | destToken, 85 | amount, 86 | parts, 87 | flags, 88 | destTokenEthPriceTimesGasPrice 89 | ); 90 | } 91 | } 92 | 93 | 94 | contract OneSplitAave is OneSplitBaseWrap { 95 | function _swap( 96 | IERC20 fromToken, 97 | IERC20 destToken, 98 | uint256 amount, 99 | uint256[] memory distribution, 100 | uint256 flags 101 | ) internal { 102 | _aaveSwap( 103 | fromToken, 104 | destToken, 105 | amount, 106 | distribution, 107 | flags 108 | ); 109 | } 110 | 111 | function _aaveSwap( 112 | IERC20 fromToken, 113 | IERC20 destToken, 114 | uint256 amount, 115 | uint256[] memory distribution, 116 | uint256 flags 117 | ) private { 118 | if (fromToken == destToken) { 119 | return; 120 | } 121 | 122 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_AAVE)) { 123 | IERC20 underlying = aaveRegistry.tokenByAToken(IAaveToken(address(fromToken))); 124 | if (underlying != IERC20(0)) { 125 | IAaveToken(address(fromToken)).redeem(amount); 126 | 127 | return _aaveSwap( 128 | underlying, 129 | destToken, 130 | amount, 131 | distribution, 132 | flags 133 | ); 134 | } 135 | 136 | underlying = aaveRegistry.tokenByAToken(IAaveToken(address(destToken))); 137 | if (underlying != IERC20(0)) { 138 | super._swap( 139 | fromToken, 140 | underlying, 141 | amount, 142 | distribution, 143 | flags 144 | ); 145 | 146 | uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); 147 | 148 | underlying.universalApprove(aave.core(), underlyingAmount); 149 | aave.deposit.value(underlying.isETH() ? underlyingAmount : 0)( 150 | underlying.isETH() ? ETH_ADDRESS : underlying, 151 | underlyingAmount, 152 | 1101 153 | ); 154 | return; 155 | } 156 | } 157 | 158 | return super._swap( 159 | fromToken, 160 | destToken, 161 | amount, 162 | distribution, 163 | flags 164 | ); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /contracts/OneSplitBdai.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IBdai.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitBdaiBase { 8 | IBdai internal constant bdai = IBdai(0x6a4FFAafa8DD400676Df8076AD6c724867b0e2e8); 9 | IERC20 internal constant btu = IERC20(0xb683D83a532e2Cb7DFa5275eED3698436371cc9f); 10 | } 11 | 12 | 13 | contract OneSplitBdaiView is OneSplitViewWrapBase, OneSplitBdaiBase { 14 | function getExpectedReturnWithGas( 15 | IERC20 fromToken, 16 | IERC20 destToken, 17 | uint256 amount, 18 | uint256 parts, 19 | uint256 flags, 20 | uint256 destTokenEthPriceTimesGasPrice 21 | ) 22 | public 23 | view 24 | returns( 25 | uint256 returnAmount, 26 | uint256 estimateGasAmount, 27 | uint256[] memory distribution 28 | ) 29 | { 30 | if (fromToken == destToken) { 31 | return (amount, 0, new uint256[](DEXES_COUNT)); 32 | } 33 | 34 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_BDAI)) { 35 | if (fromToken == IERC20(bdai)) { 36 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 37 | dai, 38 | destToken, 39 | amount, 40 | parts, 41 | flags, 42 | destTokenEthPriceTimesGasPrice 43 | ); 44 | return (returnAmount, estimateGasAmount + 227_000, distribution); 45 | } 46 | 47 | if (destToken == IERC20(bdai)) { 48 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 49 | fromToken, 50 | dai, 51 | amount, 52 | parts, 53 | flags, 54 | destTokenEthPriceTimesGasPrice 55 | ); 56 | return (returnAmount, estimateGasAmount + 295_000, distribution); 57 | } 58 | } 59 | 60 | return super.getExpectedReturnWithGas( 61 | fromToken, 62 | destToken, 63 | amount, 64 | parts, 65 | flags, 66 | destTokenEthPriceTimesGasPrice 67 | ); 68 | } 69 | } 70 | 71 | 72 | contract OneSplitBdai is OneSplitBaseWrap, OneSplitBdaiBase { 73 | function _swap( 74 | IERC20 fromToken, 75 | IERC20 destToken, 76 | uint256 amount, 77 | uint256[] memory distribution, 78 | uint256 flags 79 | ) internal { 80 | if (fromToken == destToken) { 81 | return; 82 | } 83 | 84 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_BDAI)) { 85 | if (fromToken == IERC20(bdai)) { 86 | bdai.exit(amount); 87 | 88 | uint256 btuBalance = btu.balanceOf(address(this)); 89 | if (btuBalance > 0) { 90 | (,uint256[] memory btuDistribution) = getExpectedReturn( 91 | btu, 92 | destToken, 93 | btuBalance, 94 | 1, 95 | flags 96 | ); 97 | 98 | _swap( 99 | btu, 100 | destToken, 101 | btuBalance, 102 | btuDistribution, 103 | flags 104 | ); 105 | } 106 | 107 | return super._swap( 108 | dai, 109 | destToken, 110 | amount, 111 | distribution, 112 | flags 113 | ); 114 | } 115 | 116 | if (destToken == IERC20(bdai)) { 117 | super._swap(fromToken, dai, amount, distribution, flags); 118 | 119 | uint256 daiBalance = dai.balanceOf(address(this)); 120 | dai.universalApprove(address(bdai), daiBalance); 121 | bdai.join(daiBalance); 122 | return; 123 | } 124 | } 125 | 126 | return super._swap(fromToken, destToken, amount, distribution, flags); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /contracts/OneSplitChai.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IChai.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitChaiView is OneSplitViewWrapBase { 8 | function getExpectedReturnWithGas( 9 | IERC20 fromToken, 10 | IERC20 destToken, 11 | uint256 amount, 12 | uint256 parts, 13 | uint256 flags, 14 | uint256 destTokenEthPriceTimesGasPrice 15 | ) 16 | public 17 | view 18 | returns( 19 | uint256 returnAmount, 20 | uint256 estimateGasAmount, 21 | uint256[] memory distribution 22 | ) 23 | { 24 | if (fromToken == destToken) { 25 | return (amount, 0, new uint256[](DEXES_COUNT)); 26 | } 27 | 28 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_CHAI)) { 29 | if (fromToken == IERC20(chai)) { 30 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 31 | dai, 32 | destToken, 33 | chai.chaiToDai(amount), 34 | parts, 35 | flags, 36 | destTokenEthPriceTimesGasPrice 37 | ); 38 | return (returnAmount, estimateGasAmount + 197_000, distribution); 39 | } 40 | 41 | if (destToken == IERC20(chai)) { 42 | uint256 price = chai.chaiPrice(); 43 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 44 | fromToken, 45 | dai, 46 | amount, 47 | parts, 48 | flags, 49 | destTokenEthPriceTimesGasPrice.mul(1e18).div(price) 50 | ); 51 | return (returnAmount.mul(price).div(1e18), estimateGasAmount + 168_000, distribution); 52 | } 53 | } 54 | 55 | return super.getExpectedReturnWithGas( 56 | fromToken, 57 | destToken, 58 | amount, 59 | parts, 60 | flags, 61 | destTokenEthPriceTimesGasPrice 62 | ); 63 | } 64 | } 65 | 66 | 67 | contract OneSplitChai is OneSplitBaseWrap { 68 | function _swap( 69 | IERC20 fromToken, 70 | IERC20 destToken, 71 | uint256 amount, 72 | uint256[] memory distribution, 73 | uint256 flags 74 | ) internal { 75 | if (fromToken == destToken) { 76 | return; 77 | } 78 | 79 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_CHAI)) { 80 | if (fromToken == IERC20(chai)) { 81 | chai.exit(address(this), amount); 82 | 83 | return super._swap( 84 | dai, 85 | destToken, 86 | dai.balanceOf(address(this)), 87 | distribution, 88 | flags 89 | ); 90 | } 91 | 92 | if (destToken == IERC20(chai)) { 93 | super._swap( 94 | fromToken, 95 | dai, 96 | amount, 97 | distribution, 98 | flags 99 | ); 100 | 101 | uint256 daiBalance = dai.balanceOf(address(this)); 102 | dai.universalApprove(address(chai), daiBalance); 103 | chai.join(address(this), daiBalance); 104 | return; 105 | } 106 | } 107 | 108 | return super._swap( 109 | fromToken, 110 | destToken, 111 | amount, 112 | distribution, 113 | flags 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /contracts/OneSplitCompound.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/ICompound.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitCompoundView is OneSplitViewWrapBase { 8 | function getExpectedReturnWithGas( 9 | IERC20 fromToken, 10 | IERC20 destToken, 11 | uint256 amount, 12 | uint256 parts, 13 | uint256 flags, 14 | uint256 destTokenEthPriceTimesGasPrice 15 | ) 16 | public 17 | view 18 | returns( 19 | uint256 returnAmount, 20 | uint256 estimateGasAmount, 21 | uint256[] memory distribution 22 | ) 23 | { 24 | return _compoundGetExpectedReturn( 25 | fromToken, 26 | destToken, 27 | amount, 28 | parts, 29 | flags, 30 | destTokenEthPriceTimesGasPrice 31 | ); 32 | } 33 | 34 | function _compoundGetExpectedReturn( 35 | IERC20 fromToken, 36 | IERC20 destToken, 37 | uint256 amount, 38 | uint256 parts, 39 | uint256 flags, 40 | uint256 destTokenEthPriceTimesGasPrice 41 | ) 42 | private 43 | view 44 | returns( 45 | uint256 returnAmount, 46 | uint256 estimateGasAmount, 47 | uint256[] memory distribution 48 | ) 49 | { 50 | if (fromToken == destToken) { 51 | return (amount, 0, new uint256[](DEXES_COUNT)); 52 | } 53 | 54 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_COMPOUND)) { 55 | IERC20 underlying = compoundRegistry.tokenByCToken(ICompoundToken(address(fromToken))); 56 | if (underlying != IERC20(0)) { 57 | uint256 compoundRate = ICompoundToken(address(fromToken)).exchangeRateStored(); 58 | (returnAmount, estimateGasAmount, distribution) = _compoundGetExpectedReturn( 59 | underlying, 60 | destToken, 61 | amount.mul(compoundRate).div(1e18), 62 | parts, 63 | flags, 64 | destTokenEthPriceTimesGasPrice 65 | ); 66 | return (returnAmount, estimateGasAmount + 295_000, distribution); 67 | } 68 | 69 | underlying = compoundRegistry.tokenByCToken(ICompoundToken(address(destToken))); 70 | if (underlying != IERC20(0)) { 71 | uint256 _destTokenEthPriceTimesGasPrice = destTokenEthPriceTimesGasPrice; 72 | uint256 compoundRate = ICompoundToken(address(destToken)).exchangeRateStored(); 73 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 74 | fromToken, 75 | underlying, 76 | amount, 77 | parts, 78 | flags, 79 | _destTokenEthPriceTimesGasPrice.mul(compoundRate).div(1e18) 80 | ); 81 | return (returnAmount.mul(1e18).div(compoundRate), estimateGasAmount + 430_000, distribution); 82 | } 83 | } 84 | 85 | return super.getExpectedReturnWithGas( 86 | fromToken, 87 | destToken, 88 | amount, 89 | parts, 90 | flags, 91 | destTokenEthPriceTimesGasPrice 92 | ); 93 | } 94 | } 95 | 96 | 97 | contract OneSplitCompound is OneSplitBaseWrap { 98 | function _swap( 99 | IERC20 fromToken, 100 | IERC20 destToken, 101 | uint256 amount, 102 | uint256[] memory distribution, 103 | uint256 flags 104 | ) internal { 105 | _compoundSwap( 106 | fromToken, 107 | destToken, 108 | amount, 109 | distribution, 110 | flags 111 | ); 112 | } 113 | 114 | function _compoundSwap( 115 | IERC20 fromToken, 116 | IERC20 destToken, 117 | uint256 amount, 118 | uint256[] memory distribution, 119 | uint256 flags 120 | ) private { 121 | if (fromToken == destToken) { 122 | return; 123 | } 124 | 125 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_COMPOUND)) { 126 | IERC20 underlying = compoundRegistry.tokenByCToken(ICompoundToken(address(fromToken))); 127 | if (underlying != IERC20(0)) { 128 | ICompoundToken(address(fromToken)).redeem(amount); 129 | uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); 130 | 131 | return _compoundSwap( 132 | underlying, 133 | destToken, 134 | underlyingAmount, 135 | distribution, 136 | flags 137 | ); 138 | } 139 | 140 | underlying = compoundRegistry.tokenByCToken(ICompoundToken(address(destToken))); 141 | if (underlying != IERC20(0)) { 142 | super._swap( 143 | fromToken, 144 | underlying, 145 | amount, 146 | distribution, 147 | flags 148 | ); 149 | 150 | uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); 151 | 152 | if (underlying.isETH()) { 153 | cETH.mint.value(underlyingAmount)(); 154 | } else { 155 | underlying.universalApprove(address(destToken), underlyingAmount); 156 | ICompoundToken(address(destToken)).mint(underlyingAmount); 157 | } 158 | return; 159 | } 160 | } 161 | 162 | return super._swap( 163 | fromToken, 164 | destToken, 165 | amount, 166 | distribution, 167 | flags 168 | ); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /contracts/OneSplitDMM.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IDMM.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitDMMBase { 8 | IDMMController internal constant _dmmController = IDMMController(0x4CB120Dd1D33C9A3De8Bc15620C7Cd43418d77E2); 9 | 10 | function _getDMMUnderlyingToken(IERC20 token) internal view returns(IERC20) { 11 | (bool success, bytes memory data) = address(_dmmController).staticcall( 12 | abi.encodeWithSelector( 13 | _dmmController.getUnderlyingTokenForDmm.selector, 14 | token 15 | ) 16 | ); 17 | 18 | if (!success || data.length == 0) { 19 | return IERC20(-1); 20 | } 21 | 22 | return abi.decode(data, (IERC20)); 23 | } 24 | 25 | function _getDMMExchangeRate(IDMM dmm) internal view returns(uint256) { 26 | (bool success, bytes memory data) = address(dmm).staticcall( 27 | abi.encodeWithSelector( 28 | dmm.getCurrentExchangeRate.selector 29 | ) 30 | ); 31 | 32 | if (!success || data.length == 0) { 33 | return 0; 34 | } 35 | 36 | return abi.decode(data, (uint256)); 37 | } 38 | } 39 | 40 | 41 | contract OneSplitDMMView is OneSplitViewWrapBase, OneSplitDMMBase { 42 | function getExpectedReturnWithGas( 43 | IERC20 fromToken, 44 | IERC20 destToken, 45 | uint256 amount, 46 | uint256 parts, 47 | uint256 flags, 48 | uint256 destTokenEthPriceTimesGasPrice 49 | ) 50 | public 51 | view 52 | returns( 53 | uint256 returnAmount, 54 | uint256 estimateGasAmount, 55 | uint256[] memory distribution 56 | ) 57 | { 58 | return _dmmGetExpectedReturn( 59 | fromToken, 60 | destToken, 61 | amount, 62 | parts, 63 | flags, 64 | destTokenEthPriceTimesGasPrice 65 | ); 66 | } 67 | 68 | function _dmmGetExpectedReturn( 69 | IERC20 fromToken, 70 | IERC20 destToken, 71 | uint256 amount, 72 | uint256 parts, 73 | uint256 flags, 74 | uint256 destTokenEthPriceTimesGasPrice 75 | ) 76 | private 77 | view 78 | returns( 79 | uint256 returnAmount, 80 | uint256 estimateGasAmount, 81 | uint256[] memory distribution 82 | ) 83 | { 84 | if (fromToken == destToken) { 85 | return (amount, 0, new uint256[](DEXES_COUNT)); 86 | } 87 | 88 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_DMM)) { 89 | IERC20 underlying = _getDMMUnderlyingToken(fromToken); 90 | if (underlying != IERC20(-1)) { 91 | if (underlying == weth) { 92 | underlying = ETH_ADDRESS; 93 | } 94 | IERC20 _fromToken = fromToken; 95 | (returnAmount, estimateGasAmount, distribution) = _dmmGetExpectedReturn( 96 | underlying, 97 | destToken, 98 | amount.mul(_getDMMExchangeRate(IDMM(address(_fromToken)))).div(1e18), 99 | parts, 100 | flags, 101 | destTokenEthPriceTimesGasPrice 102 | ); 103 | return (returnAmount, estimateGasAmount + 295_000, distribution); 104 | } 105 | 106 | underlying = _getDMMUnderlyingToken(destToken); 107 | if (underlying != IERC20(-1)) { 108 | if (underlying == weth) { 109 | underlying = ETH_ADDRESS; 110 | } 111 | uint256 price = _getDMMExchangeRate(IDMM(address(destToken))); 112 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 113 | fromToken, 114 | underlying, 115 | amount, 116 | parts, 117 | flags, 118 | destTokenEthPriceTimesGasPrice.mul(price).div(1e18) 119 | ); 120 | return ( 121 | returnAmount.mul(1e18).div(price), 122 | estimateGasAmount + 430_000, 123 | distribution 124 | ); 125 | } 126 | } 127 | 128 | return super.getExpectedReturnWithGas( 129 | fromToken, 130 | destToken, 131 | amount, 132 | parts, 133 | flags, 134 | destTokenEthPriceTimesGasPrice 135 | ); 136 | } 137 | } 138 | 139 | 140 | contract OneSplitDMM is OneSplitBaseWrap, OneSplitDMMBase { 141 | function _swap( 142 | IERC20 fromToken, 143 | IERC20 destToken, 144 | uint256 amount, 145 | uint256[] memory distribution, 146 | uint256 flags 147 | ) internal { 148 | _dmmSwap( 149 | fromToken, 150 | destToken, 151 | amount, 152 | distribution, 153 | flags 154 | ); 155 | } 156 | 157 | function _dmmSwap( 158 | IERC20 fromToken, 159 | IERC20 destToken, 160 | uint256 amount, 161 | uint256[] memory distribution, 162 | uint256 flags 163 | ) private { 164 | if (fromToken == destToken) { 165 | return; 166 | } 167 | 168 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_DMM)) { 169 | IERC20 underlying = _getDMMUnderlyingToken(fromToken); 170 | if (underlying != IERC20(-1)) { 171 | IDMM(address(fromToken)).redeem(amount); 172 | uint256 balance = underlying.universalBalanceOf(address(this)); 173 | if (underlying == weth) { 174 | weth.withdraw(balance); 175 | } 176 | _dmmSwap( 177 | (underlying == weth) ? ETH_ADDRESS : underlying, 178 | destToken, 179 | balance, 180 | distribution, 181 | flags 182 | ); 183 | } 184 | 185 | underlying = _getDMMUnderlyingToken(destToken); 186 | if (underlying != IERC20(-1)) { 187 | super._swap( 188 | fromToken, 189 | (underlying == weth) ? ETH_ADDRESS : underlying, 190 | amount, 191 | distribution, 192 | flags 193 | ); 194 | 195 | uint256 underlyingAmount = ((underlying == weth) ? ETH_ADDRESS : underlying).universalBalanceOf(address(this)); 196 | if (underlying == weth) { 197 | weth.deposit.value(underlyingAmount); 198 | } 199 | 200 | underlying.universalApprove(address(destToken), underlyingAmount); 201 | IDMM(address(destToken)).mint(underlyingAmount); 202 | return; 203 | } 204 | } 205 | 206 | return super._swap( 207 | fromToken, 208 | destToken, 209 | amount, 210 | distribution, 211 | flags 212 | ); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /contracts/OneSplitFulcrum.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IFulcrum.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitFulcrumBase { 8 | using UniversalERC20 for IERC20; 9 | 10 | function _isFulcrumToken(IERC20 token) internal view returns(IERC20) { 11 | if (token.isETH()) { 12 | return IERC20(-1); 13 | } 14 | 15 | (bool success, bytes memory data) = address(token).staticcall.gas(5000)(abi.encodeWithSignature( 16 | "name()" 17 | )); 18 | if (!success) { 19 | return IERC20(-1); 20 | } 21 | 22 | bool foundBZX = false; 23 | for (uint i = 0; i + 6 < data.length; i++) { 24 | if (data[i + 0] == "F" && 25 | data[i + 1] == "u" && 26 | data[i + 2] == "l" && 27 | data[i + 3] == "c" && 28 | data[i + 4] == "r" && 29 | data[i + 5] == "u" && 30 | data[i + 6] == "m") 31 | { 32 | foundBZX = true; 33 | break; 34 | } 35 | } 36 | if (!foundBZX) { 37 | return IERC20(-1); 38 | } 39 | 40 | (success, data) = address(token).staticcall.gas(5000)(abi.encodeWithSelector( 41 | IFulcrumToken(address(token)).loanTokenAddress.selector 42 | )); 43 | if (!success) { 44 | return IERC20(-1); 45 | } 46 | 47 | return abi.decode(data, (IERC20)); 48 | } 49 | } 50 | 51 | 52 | contract OneSplitFulcrumView is OneSplitViewWrapBase, OneSplitFulcrumBase { 53 | function getExpectedReturnWithGas( 54 | IERC20 fromToken, 55 | IERC20 destToken, 56 | uint256 amount, 57 | uint256 parts, 58 | uint256 flags, 59 | uint256 destTokenEthPriceTimesGasPrice 60 | ) 61 | public 62 | view 63 | returns( 64 | uint256 returnAmount, 65 | uint256 estimateGasAmount, 66 | uint256[] memory distribution 67 | ) 68 | { 69 | return _fulcrumGetExpectedReturn( 70 | fromToken, 71 | destToken, 72 | amount, 73 | parts, 74 | flags, 75 | destTokenEthPriceTimesGasPrice 76 | ); 77 | } 78 | 79 | function _fulcrumGetExpectedReturn( 80 | IERC20 fromToken, 81 | IERC20 destToken, 82 | uint256 amount, 83 | uint256 parts, 84 | uint256 flags, 85 | uint256 destTokenEthPriceTimesGasPrice 86 | ) 87 | private 88 | view 89 | returns( 90 | uint256 returnAmount, 91 | uint256 estimateGasAmount, 92 | uint256[] memory distribution 93 | ) 94 | { 95 | if (fromToken == destToken) { 96 | return (amount, 0, new uint256[](DEXES_COUNT)); 97 | } 98 | 99 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_FULCRUM)) { 100 | IERC20 underlying = _isFulcrumToken(fromToken); 101 | if (underlying != IERC20(-1)) { 102 | uint256 fulcrumRate = IFulcrumToken(address(fromToken)).tokenPrice(); 103 | (returnAmount, estimateGasAmount, distribution) = _fulcrumGetExpectedReturn( 104 | underlying, 105 | destToken, 106 | amount.mul(fulcrumRate).div(1e18), 107 | parts, 108 | flags, 109 | destTokenEthPriceTimesGasPrice 110 | ); 111 | return (returnAmount, estimateGasAmount + 381_000, distribution); 112 | } 113 | 114 | underlying = _isFulcrumToken(destToken); 115 | if (underlying != IERC20(-1)) { 116 | uint256 _destTokenEthPriceTimesGasPrice = destTokenEthPriceTimesGasPrice; 117 | uint256 fulcrumRate = IFulcrumToken(address(destToken)).tokenPrice(); 118 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 119 | fromToken, 120 | underlying, 121 | amount, 122 | parts, 123 | flags, 124 | _destTokenEthPriceTimesGasPrice.mul(fulcrumRate).div(1e18) 125 | ); 126 | return (returnAmount.mul(1e18).div(fulcrumRate), estimateGasAmount + 354_000, distribution); 127 | } 128 | } 129 | 130 | return super.getExpectedReturnWithGas( 131 | fromToken, 132 | destToken, 133 | amount, 134 | parts, 135 | flags, 136 | destTokenEthPriceTimesGasPrice 137 | ); 138 | } 139 | } 140 | 141 | 142 | contract OneSplitFulcrum is OneSplitBaseWrap, OneSplitFulcrumBase { 143 | function _swap( 144 | IERC20 fromToken, 145 | IERC20 destToken, 146 | uint256 amount, 147 | uint256[] memory distribution, 148 | uint256 flags 149 | ) internal { 150 | _fulcrumSwap( 151 | fromToken, 152 | destToken, 153 | amount, 154 | distribution, 155 | flags 156 | ); 157 | } 158 | 159 | function _fulcrumSwap( 160 | IERC20 fromToken, 161 | IERC20 destToken, 162 | uint256 amount, 163 | uint256[] memory distribution, 164 | uint256 flags 165 | ) private { 166 | if (fromToken == destToken) { 167 | return; 168 | } 169 | 170 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_FULCRUM)) { 171 | IERC20 underlying = _isFulcrumToken(fromToken); 172 | if (underlying != IERC20(-1)) { 173 | if (underlying.isETH()) { 174 | IFulcrumToken(address(fromToken)).burnToEther(address(this), amount); 175 | } else { 176 | IFulcrumToken(address(fromToken)).burn(address(this), amount); 177 | } 178 | 179 | uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); 180 | 181 | return super._swap( 182 | underlying, 183 | destToken, 184 | underlyingAmount, 185 | distribution, 186 | flags 187 | ); 188 | } 189 | 190 | underlying = _isFulcrumToken(destToken); 191 | if (underlying != IERC20(-1)) { 192 | super._swap( 193 | fromToken, 194 | underlying, 195 | amount, 196 | distribution, 197 | flags 198 | ); 199 | 200 | uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); 201 | 202 | if (underlying.isETH()) { 203 | IFulcrumToken(address(destToken)).mintWithEther.value(underlyingAmount)(address(this)); 204 | } else { 205 | underlying.universalApprove(address(destToken), underlyingAmount); 206 | IFulcrumToken(address(destToken)).mint(address(this), underlyingAmount); 207 | } 208 | return; 209 | } 210 | } 211 | 212 | return super._swap( 213 | fromToken, 214 | destToken, 215 | amount, 216 | distribution, 217 | flags 218 | ); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /contracts/OneSplitIdle.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IIdle.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitIdleBase { 8 | function _idleTokens() internal pure returns(IIdle[8] memory) { 9 | // https://developers.idle.finance/contracts-and-codebase 10 | return [ 11 | // V3 12 | IIdle(0x78751B12Da02728F467A44eAc40F5cbc16Bd7934), 13 | IIdle(0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6), 14 | IIdle(0x63D27B3DA94A9E871222CB0A32232674B02D2f2D), 15 | IIdle(0x1846bdfDB6A0f5c473dEc610144513bd071999fB), 16 | IIdle(0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C), 17 | IIdle(0x42740698959761BAF1B06baa51EfBD88CB1D862B), 18 | // V2 19 | IIdle(0x10eC0D497824e342bCB0EDcE00959142aAa766dD), 20 | IIdle(0xeB66ACc3d011056B00ea521F8203580C2E5d3991) 21 | ]; 22 | } 23 | } 24 | 25 | 26 | contract OneSplitIdleView is OneSplitViewWrapBase, OneSplitIdleBase { 27 | function getExpectedReturnWithGas( 28 | IERC20 fromToken, 29 | IERC20 destToken, 30 | uint256 amount, 31 | uint256 parts, 32 | uint256 flags, 33 | uint256 destTokenEthPriceTimesGasPrice 34 | ) 35 | public 36 | view 37 | returns( 38 | uint256 returnAmount, 39 | uint256 estimateGasAmount, 40 | uint256[] memory distribution 41 | ) 42 | { 43 | return _idleGetExpectedReturn( 44 | fromToken, 45 | destToken, 46 | amount, 47 | parts, 48 | flags, 49 | destTokenEthPriceTimesGasPrice 50 | ); 51 | } 52 | 53 | function _idleGetExpectedReturn( 54 | IERC20 fromToken, 55 | IERC20 destToken, 56 | uint256 amount, 57 | uint256 parts, 58 | uint256 flags, 59 | uint256 destTokenEthPriceTimesGasPrice 60 | ) 61 | internal 62 | view 63 | returns( 64 | uint256 returnAmount, 65 | uint256 estimateGasAmount, 66 | uint256[] memory distribution 67 | ) 68 | { 69 | if (fromToken == destToken) { 70 | return (amount, 0, new uint256[](DEXES_COUNT)); 71 | } 72 | 73 | if (!flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == !flags.check(FLAG_DISABLE_IDLE)) { 74 | IIdle[8] memory tokens = _idleTokens(); 75 | 76 | for (uint i = 0; i < tokens.length; i++) { 77 | if (fromToken == IERC20(tokens[i])) { 78 | (returnAmount, estimateGasAmount, distribution) = _idleGetExpectedReturn( 79 | tokens[i].token(), 80 | destToken, 81 | amount.mul(tokens[i].tokenPrice()).div(1e18), 82 | parts, 83 | flags, 84 | destTokenEthPriceTimesGasPrice 85 | ); 86 | return (returnAmount, estimateGasAmount + 2_400_000, distribution); 87 | } 88 | } 89 | 90 | for (uint i = 0; i < tokens.length; i++) { 91 | if (destToken == IERC20(tokens[i])) { 92 | uint256 _destTokenEthPriceTimesGasPrice = destTokenEthPriceTimesGasPrice; 93 | uint256 _price = tokens[i].tokenPrice(); 94 | IERC20 token = tokens[i].token(); 95 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 96 | fromToken, 97 | token, 98 | amount, 99 | parts, 100 | flags, 101 | _destTokenEthPriceTimesGasPrice.mul(_price).div(1e18) 102 | ); 103 | return (returnAmount.mul(1e18).div(_price), estimateGasAmount + 1_300_000, distribution); 104 | } 105 | } 106 | } 107 | 108 | return super.getExpectedReturnWithGas( 109 | fromToken, 110 | destToken, 111 | amount, 112 | parts, 113 | flags, 114 | destTokenEthPriceTimesGasPrice 115 | ); 116 | } 117 | } 118 | 119 | 120 | contract OneSplitIdle is OneSplitBaseWrap, OneSplitIdleBase { 121 | function _swap( 122 | IERC20 fromToken, 123 | IERC20 destToken, 124 | uint256 amount, 125 | uint256[] memory distribution, 126 | uint256 flags 127 | ) internal { 128 | _idleSwap( 129 | fromToken, 130 | destToken, 131 | amount, 132 | distribution, 133 | flags 134 | ); 135 | } 136 | 137 | function _idleSwap( 138 | IERC20 fromToken, 139 | IERC20 destToken, 140 | uint256 amount, 141 | uint256[] memory distribution, 142 | uint256 flags 143 | ) internal { 144 | if (!flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == !flags.check(FLAG_DISABLE_IDLE)) { 145 | IIdle[8] memory tokens = _idleTokens(); 146 | 147 | for (uint i = 0; i < tokens.length; i++) { 148 | if (fromToken == IERC20(tokens[i])) { 149 | IERC20 underlying = tokens[i].token(); 150 | uint256 minted = tokens[i].redeemIdleToken(amount, true, new uint256[](0)); 151 | _idleSwap(underlying, destToken, minted, distribution, flags); 152 | return; 153 | } 154 | } 155 | 156 | for (uint i = 0; i < tokens.length; i++) { 157 | if (destToken == IERC20(tokens[i])) { 158 | IERC20 underlying = tokens[i].token(); 159 | super._swap(fromToken, underlying, amount, distribution, flags); 160 | 161 | uint256 underlyingBalance = underlying.balanceOf(address(this)); 162 | underlying.universalApprove(address(tokens[i]), underlyingBalance); 163 | tokens[i].mintIdleToken(underlyingBalance, new uint256[](0)); 164 | return; 165 | } 166 | } 167 | } 168 | 169 | return super._swap(fromToken, destToken, amount, distribution, flags); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /contracts/OneSplitIearn.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IIearn.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitIearnBase { 8 | function _yTokens() internal pure returns(IIearn[13] memory) { 9 | return [ 10 | IIearn(0x16de59092dAE5CcF4A1E6439D611fd0653f0Bd01), 11 | IIearn(0x04Aa51bbcB46541455cCF1B8bef2ebc5d3787EC9), 12 | IIearn(0x73a052500105205d34Daf004eAb301916DA8190f), 13 | IIearn(0x83f798e925BcD4017Eb265844FDDAbb448f1707D), 14 | IIearn(0xd6aD7a6750A7593E092a9B218d66C0A814a3436e), 15 | IIearn(0xF61718057901F84C4eEC4339EF8f0D86D2B45600), 16 | IIearn(0x04bC0Ab673d88aE9dbC9DA2380cB6B79C4BCa9aE), 17 | IIearn(0xC2cB1040220768554cf699b0d863A3cd4324ce32), 18 | IIearn(0xE6354ed5bC4b393a5Aad09f21c46E101e692d447), 19 | IIearn(0x26EA744E5B887E5205727f55dFBE8685e3b21951), 20 | IIearn(0x99d1Fa417f94dcD62BfE781a1213c092a47041Bc), 21 | IIearn(0x9777d7E2b60bB01759D0E2f8be2095df444cb07E), 22 | IIearn(0x1bE5d71F2dA660BFdee8012dDc58D024448A0A59) 23 | ]; 24 | } 25 | } 26 | 27 | 28 | contract OneSplitIearnView is OneSplitViewWrapBase, OneSplitIearnBase { 29 | function getExpectedReturnWithGas( 30 | IERC20 fromToken, 31 | IERC20 destToken, 32 | uint256 amount, 33 | uint256 parts, 34 | uint256 flags, 35 | uint256 destTokenEthPriceTimesGasPrice 36 | ) 37 | public 38 | view 39 | returns( 40 | uint256 returnAmount, 41 | uint256 estimateGasAmount, 42 | uint256[] memory distribution 43 | ) 44 | { 45 | return _iearnGetExpectedReturn( 46 | fromToken, 47 | destToken, 48 | amount, 49 | parts, 50 | flags, 51 | destTokenEthPriceTimesGasPrice 52 | ); 53 | } 54 | 55 | function _iearnGetExpectedReturn( 56 | IERC20 fromToken, 57 | IERC20 destToken, 58 | uint256 amount, 59 | uint256 parts, 60 | uint256 flags, 61 | uint256 destTokenEthPriceTimesGasPrice 62 | ) 63 | private 64 | view 65 | returns( 66 | uint256 returnAmount, 67 | uint256 estimateGasAmount, 68 | uint256[] memory distribution 69 | ) 70 | { 71 | if (fromToken == destToken) { 72 | return (amount, 0, new uint256[](DEXES_COUNT)); 73 | } 74 | 75 | if (!flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == !flags.check(FLAG_DISABLE_IEARN)) { 76 | IIearn[13] memory yTokens = _yTokens(); 77 | 78 | for (uint i = 0; i < yTokens.length; i++) { 79 | if (fromToken == IERC20(yTokens[i])) { 80 | (returnAmount, estimateGasAmount, distribution) = _iearnGetExpectedReturn( 81 | yTokens[i].token(), 82 | destToken, 83 | amount 84 | .mul(yTokens[i].calcPoolValueInToken()) 85 | .div(yTokens[i].totalSupply()), 86 | parts, 87 | flags, 88 | destTokenEthPriceTimesGasPrice 89 | ); 90 | return (returnAmount, estimateGasAmount + 260_000, distribution); 91 | } 92 | } 93 | 94 | for (uint i = 0; i < yTokens.length; i++) { 95 | if (destToken == IERC20(yTokens[i])) { 96 | uint256 _destTokenEthPriceTimesGasPrice = destTokenEthPriceTimesGasPrice; 97 | IERC20 token = yTokens[i].token(); 98 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 99 | fromToken, 100 | token, 101 | amount, 102 | parts, 103 | flags, 104 | _destTokenEthPriceTimesGasPrice 105 | .mul(yTokens[i].calcPoolValueInToken()) 106 | .div(yTokens[i].totalSupply()) 107 | ); 108 | 109 | return( 110 | returnAmount 111 | .mul(yTokens[i].totalSupply()) 112 | .div(yTokens[i].calcPoolValueInToken()), 113 | estimateGasAmount + 743_000, 114 | distribution 115 | ); 116 | } 117 | } 118 | } 119 | 120 | return super.getExpectedReturnWithGas( 121 | fromToken, 122 | destToken, 123 | amount, 124 | parts, 125 | flags, 126 | destTokenEthPriceTimesGasPrice 127 | ); 128 | } 129 | } 130 | 131 | 132 | contract OneSplitIearn is OneSplitBaseWrap, OneSplitIearnBase { 133 | function _swap( 134 | IERC20 fromToken, 135 | IERC20 destToken, 136 | uint256 amount, 137 | uint256[] memory distribution, 138 | uint256 flags 139 | ) internal { 140 | _iearnSwap( 141 | fromToken, 142 | destToken, 143 | amount, 144 | distribution, 145 | flags 146 | ); 147 | } 148 | 149 | function _iearnSwap( 150 | IERC20 fromToken, 151 | IERC20 destToken, 152 | uint256 amount, 153 | uint256[] memory distribution, 154 | uint256 flags 155 | ) private { 156 | if (fromToken == destToken) { 157 | return; 158 | } 159 | 160 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_IEARN)) { 161 | IIearn[13] memory yTokens = _yTokens(); 162 | 163 | for (uint i = 0; i < yTokens.length; i++) { 164 | if (fromToken == IERC20(yTokens[i])) { 165 | IERC20 underlying = yTokens[i].token(); 166 | yTokens[i].withdraw(amount); 167 | _iearnSwap(underlying, destToken, underlying.balanceOf(address(this)), distribution, flags); 168 | return; 169 | } 170 | } 171 | 172 | for (uint i = 0; i < yTokens.length; i++) { 173 | if (destToken == IERC20(yTokens[i])) { 174 | IERC20 underlying = yTokens[i].token(); 175 | super._swap(fromToken, underlying, amount, distribution, flags); 176 | 177 | uint256 underlyingBalance = underlying.balanceOf(address(this)); 178 | underlying.universalApprove(address(yTokens[i]), underlyingBalance); 179 | yTokens[i].deposit(underlyingBalance); 180 | return; 181 | } 182 | } 183 | } 184 | 185 | return super._swap(fromToken, destToken, amount, distribution, flags); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /contracts/OneSplitMStable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/IChai.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitMStableView is OneSplitViewWrapBase { 8 | function getExpectedReturnWithGas( 9 | IERC20 fromToken, 10 | IERC20 destToken, 11 | uint256 amount, 12 | uint256 parts, 13 | uint256 flags, 14 | uint256 destTokenEthPriceTimesGasPrice 15 | ) 16 | public 17 | view 18 | returns( 19 | uint256 returnAmount, 20 | uint256 estimateGasAmount, 21 | uint256[] memory distribution 22 | ) 23 | { 24 | if (fromToken == destToken) { 25 | return (amount, 0, new uint256[](DEXES_COUNT)); 26 | } 27 | 28 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_MSTABLE_MUSD)) { 29 | if (fromToken == IERC20(musd)) { 30 | { 31 | (bool valid1,, uint256 res1,) = musd_helper.getRedeemValidity(musd, amount, destToken); 32 | if (valid1) { 33 | return (res1, 300_000, new uint256[](DEXES_COUNT)); 34 | } 35 | } 36 | 37 | (bool valid,, address token) = musd_helper.suggestRedeemAsset(musd); 38 | if (valid) { 39 | (,, returnAmount,) = musd_helper.getRedeemValidity(musd, amount, IERC20(token)); 40 | if (IERC20(token) != destToken) { 41 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 42 | IERC20(token), 43 | destToken, 44 | returnAmount, 45 | parts, 46 | flags, 47 | destTokenEthPriceTimesGasPrice 48 | ); 49 | } else { 50 | distribution = new uint256[](DEXES_COUNT); 51 | } 52 | 53 | return (returnAmount, estimateGasAmount + 300_000, distribution); 54 | } 55 | } 56 | 57 | if (destToken == IERC20(musd)) { 58 | if (fromToken == usdc || fromToken == dai || fromToken == usdt || fromToken == tusd) { 59 | (,, returnAmount) = musd.getSwapOutput(fromToken, destToken, amount); 60 | return (returnAmount, 300_000, new uint256[](DEXES_COUNT)); 61 | } 62 | else { 63 | IERC20 _destToken = destToken; 64 | (bool valid,, address token) = musd_helper.suggestMintAsset(_destToken); 65 | if (valid) { 66 | if (IERC20(token) != fromToken) { 67 | (returnAmount, estimateGasAmount, distribution) = super.getExpectedReturnWithGas( 68 | fromToken, 69 | IERC20(token), 70 | amount, 71 | parts, 72 | flags, 73 | _scaleDestTokenEthPriceTimesGasPrice( 74 | _destToken, 75 | IERC20(token), 76 | destTokenEthPriceTimesGasPrice 77 | ) 78 | ); 79 | } else { 80 | returnAmount = amount; 81 | } 82 | (,, returnAmount) = musd.getSwapOutput(IERC20(token), _destToken, returnAmount); 83 | return (returnAmount, estimateGasAmount + 300_000, distribution); 84 | } 85 | } 86 | } 87 | } 88 | 89 | return super.getExpectedReturnWithGas( 90 | fromToken, 91 | destToken, 92 | amount, 93 | parts, 94 | flags, 95 | destTokenEthPriceTimesGasPrice 96 | ); 97 | } 98 | } 99 | 100 | 101 | contract OneSplitMStable is OneSplitBaseWrap { 102 | function _swap( 103 | IERC20 fromToken, 104 | IERC20 destToken, 105 | uint256 amount, 106 | uint256[] memory distribution, 107 | uint256 flags 108 | ) internal { 109 | if (fromToken == destToken) { 110 | return; 111 | } 112 | 113 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_MSTABLE_MUSD)) { 114 | if (fromToken == IERC20(musd)) { 115 | if (destToken == usdc || destToken == dai || destToken == usdt || destToken == tusd) { 116 | (,,, uint256 result) = musd_helper.getRedeemValidity(fromToken, amount, destToken); 117 | musd.redeem( 118 | destToken, 119 | result 120 | ); 121 | } 122 | else { 123 | (,,, uint256 result) = musd_helper.getRedeemValidity(fromToken, amount, dai); 124 | musd.redeem( 125 | dai, 126 | result 127 | ); 128 | super._swap( 129 | dai, 130 | destToken, 131 | dai.balanceOf(address(this)), 132 | distribution, 133 | flags 134 | ); 135 | } 136 | return; 137 | } 138 | 139 | if (destToken == IERC20(musd)) { 140 | if (fromToken == usdc || fromToken == dai || fromToken == usdt || fromToken == tusd) { 141 | fromToken.universalApprove(address(musd), amount); 142 | musd.swap( 143 | fromToken, 144 | destToken, 145 | amount, 146 | address(this) 147 | ); 148 | } 149 | else { 150 | super._swap( 151 | fromToken, 152 | dai, 153 | amount, 154 | distribution, 155 | flags 156 | ); 157 | musd.swap( 158 | dai, 159 | destToken, 160 | dai.balanceOf(address(this)), 161 | address(this) 162 | ); 163 | } 164 | return; 165 | } 166 | } 167 | 168 | return super._swap( 169 | fromToken, 170 | destToken, 171 | amount, 172 | distribution, 173 | flags 174 | ); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /contracts/OneSplitMooniswapPoolToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/math/Math.sol"; 4 | import "./OneSplitBase.sol"; 5 | import "./interface/IMooniswap.sol"; 6 | import "./UniversalERC20.sol"; 7 | 8 | contract OneSplitMooniswapTokenBase { 9 | using SafeMath for uint256; 10 | using Math for uint256; 11 | using UniversalERC20 for IERC20; 12 | 13 | struct TokenInfo { 14 | IERC20 token; 15 | uint256 reserve; 16 | } 17 | 18 | struct PoolDetails { 19 | TokenInfo[2] tokens; 20 | uint256 totalSupply; 21 | } 22 | 23 | function _getPoolDetails(IMooniswap pool) internal view returns (PoolDetails memory details) { 24 | for (uint i = 0; i < 2; i++) { 25 | IERC20 token = pool.tokens(i); 26 | details.tokens[i] = TokenInfo({ 27 | token: token, 28 | reserve: token.universalBalanceOf(address(pool)) 29 | }); 30 | } 31 | 32 | details.totalSupply = IERC20(address(pool)).totalSupply(); 33 | } 34 | } 35 | 36 | 37 | contract OneSplitMooniswapTokenView is OneSplitViewWrapBase, OneSplitMooniswapTokenBase { 38 | 39 | function getExpectedReturnWithGas( 40 | IERC20 fromToken, 41 | IERC20 toToken, 42 | uint256 amount, 43 | uint256 parts, 44 | uint256 flags, 45 | uint256 destTokenEthPriceTimesGasPrice 46 | ) 47 | public 48 | view 49 | returns ( 50 | uint256 returnAmount, 51 | uint256, 52 | uint256[] memory distribution 53 | ) 54 | { 55 | if (fromToken.eq(toToken)) { 56 | return (amount, 0, new uint256[](DEXES_COUNT)); 57 | } 58 | 59 | 60 | if (!flags.check(FLAG_DISABLE_MOONISWAP_POOL_TOKEN)) { 61 | bool isPoolTokenFrom = mooniswapRegistry.isPool(address(fromToken)); 62 | bool isPoolTokenTo = mooniswapRegistry.isPool(address(toToken)); 63 | 64 | if (isPoolTokenFrom && isPoolTokenTo) { 65 | ( 66 | uint256 returnETHAmount, 67 | uint256[] memory poolTokenFromDistribution 68 | ) = _getExpectedReturnFromMooniswapPoolToken( 69 | fromToken, 70 | ETH_ADDRESS, 71 | amount, 72 | parts, 73 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 74 | ); 75 | 76 | ( 77 | uint256 returnPoolTokenToAmount, 78 | uint256[] memory poolTokenToDistribution 79 | ) = _getExpectedReturnToMooniswapPoolToken( 80 | ETH_ADDRESS, 81 | toToken, 82 | returnETHAmount, 83 | parts, 84 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 85 | ); 86 | 87 | for (uint i = 0; i < poolTokenToDistribution.length; i++) { 88 | poolTokenFromDistribution[i] |= poolTokenToDistribution[i] << 128; 89 | } 90 | 91 | return (returnPoolTokenToAmount, 0, poolTokenFromDistribution); 92 | } 93 | 94 | if (isPoolTokenFrom) { 95 | (returnAmount, distribution) = _getExpectedReturnFromMooniswapPoolToken( 96 | fromToken, 97 | toToken, 98 | amount, 99 | parts, 100 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 101 | ); 102 | return (returnAmount, 0, distribution); 103 | } 104 | 105 | if (isPoolTokenTo) { 106 | (returnAmount, distribution) = _getExpectedReturnToMooniswapPoolToken( 107 | fromToken, 108 | toToken, 109 | amount, 110 | parts, 111 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 112 | ); 113 | return (returnAmount, 0, distribution); 114 | } 115 | } 116 | 117 | return super.getExpectedReturnWithGas( 118 | fromToken, 119 | toToken, 120 | amount, 121 | parts, 122 | flags, 123 | destTokenEthPriceTimesGasPrice 124 | ); 125 | } 126 | 127 | function _getExpectedReturnFromMooniswapPoolToken( 128 | IERC20 poolToken, 129 | IERC20 toToken, 130 | uint256 amount, 131 | uint256 parts, 132 | uint256 flags 133 | ) 134 | private 135 | view 136 | returns( 137 | uint256 returnAmount, 138 | uint256[] memory distribution 139 | ) 140 | { 141 | distribution = new uint256[](DEXES_COUNT); 142 | 143 | PoolDetails memory details = _getPoolDetails(IMooniswap(address(poolToken))); 144 | 145 | for (uint i = 0; i < 2; i++) { 146 | 147 | uint256 exchangeAmount = amount 148 | .mul(details.tokens[i].reserve) 149 | .div(details.totalSupply); 150 | 151 | if (toToken.eq(details.tokens[i].token)) { 152 | returnAmount = returnAmount.add(exchangeAmount); 153 | continue; 154 | } 155 | 156 | (uint256 ret, ,uint256[] memory dist) = super.getExpectedReturnWithGas( 157 | details.tokens[i].token, 158 | toToken, 159 | exchangeAmount, 160 | parts, 161 | flags, 162 | 0 163 | ); 164 | 165 | returnAmount = returnAmount.add(ret); 166 | for (uint j = 0; j < distribution.length; j++) { 167 | distribution[j] |= dist[j] << (i * 8); 168 | } 169 | } 170 | 171 | return (returnAmount, distribution); 172 | } 173 | 174 | function _getExpectedReturnToMooniswapPoolToken( 175 | IERC20 fromToken, 176 | IERC20 poolToken, 177 | uint256 amount, 178 | uint256 parts, 179 | uint256 flags 180 | ) 181 | private 182 | view 183 | returns( 184 | uint256 returnAmount, 185 | uint256[] memory distribution 186 | ) 187 | { 188 | distribution = new uint256[](DEXES_COUNT); 189 | 190 | PoolDetails memory details = _getPoolDetails(IMooniswap(address(poolToken))); 191 | 192 | // will overwritten to liquidity amounts 193 | uint256[2] memory amounts; 194 | amounts[0] = amount.div(2); 195 | amounts[1] = amount.sub(amounts[0]); 196 | uint256[] memory dist = new uint256[](distribution.length); 197 | for (uint i = 0; i < 2; i++) { 198 | 199 | if (fromToken.eq(details.tokens[i].token)) { 200 | continue; 201 | } 202 | 203 | (amounts[i], ,dist) = super.getExpectedReturnWithGas( 204 | fromToken, 205 | details.tokens[i].token, 206 | amounts[i], 207 | parts, 208 | flags, 209 | 0 210 | ); 211 | 212 | for (uint j = 0; j < distribution.length; j++) { 213 | distribution[j] |= dist[j] << (i * 8); 214 | } 215 | } 216 | 217 | returnAmount = uint256(-1); 218 | for (uint i = 0; i < 2; i++) { 219 | returnAmount = Math.min( 220 | returnAmount, 221 | details.totalSupply.mul(amounts[i]).div(details.tokens[i].reserve) 222 | ); 223 | } 224 | 225 | return ( 226 | returnAmount, 227 | distribution 228 | ); 229 | } 230 | 231 | } 232 | 233 | 234 | contract OneSplitMooniswapToken is OneSplitBaseWrap, OneSplitMooniswapTokenBase { 235 | function _swap( 236 | IERC20 fromToken, 237 | IERC20 toToken, 238 | uint256 amount, 239 | uint256[] memory distribution, 240 | uint256 flags 241 | ) internal { 242 | if (fromToken.eq(toToken)) { 243 | return; 244 | } 245 | 246 | if (!flags.check(FLAG_DISABLE_MOONISWAP_POOL_TOKEN)) { 247 | bool isPoolTokenFrom = mooniswapRegistry.isPool(address(fromToken)); 248 | bool isPoolTokenTo = mooniswapRegistry.isPool(address(toToken)); 249 | 250 | if (isPoolTokenFrom && isPoolTokenTo) { 251 | uint256[] memory dist = new uint256[](distribution.length); 252 | for (uint i = 0; i < distribution.length; i++) { 253 | dist[i] = distribution[i] & ((1 << 128) - 1); 254 | } 255 | 256 | uint256 ethBalanceBefore = ETH_ADDRESS.universalBalanceOf(address(this)); 257 | 258 | _swapFromMooniswapToken( 259 | fromToken, 260 | ETH_ADDRESS, 261 | amount, 262 | dist, 263 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 264 | ); 265 | 266 | for (uint i = 0; i < distribution.length; i++) { 267 | dist[i] = distribution[i] >> 128; 268 | } 269 | 270 | uint256 ethBalanceAfter = ETH_ADDRESS.universalBalanceOf(address(this)); 271 | 272 | return _swapToMooniswapToken( 273 | ETH_ADDRESS, 274 | toToken, 275 | ethBalanceAfter.sub(ethBalanceBefore), 276 | dist, 277 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 278 | ); 279 | } 280 | 281 | if (isPoolTokenFrom) { 282 | return _swapFromMooniswapToken( 283 | fromToken, 284 | toToken, 285 | amount, 286 | distribution, 287 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 288 | ); 289 | } 290 | 291 | if (isPoolTokenTo) { 292 | return _swapToMooniswapToken( 293 | fromToken, 294 | toToken, 295 | amount, 296 | distribution, 297 | FLAG_DISABLE_MOONISWAP_POOL_TOKEN 298 | ); 299 | } 300 | } 301 | 302 | return super._swap( 303 | fromToken, 304 | toToken, 305 | amount, 306 | distribution, 307 | flags 308 | ); 309 | } 310 | 311 | function _swapFromMooniswapToken( 312 | IERC20 poolToken, 313 | IERC20 toToken, 314 | uint256 amount, 315 | uint256[] memory distribution, 316 | uint256 flags 317 | ) private { 318 | IERC20[2] memory tokens = [ 319 | IMooniswap(address(poolToken)).tokens(0), 320 | IMooniswap(address(poolToken)).tokens(1) 321 | ]; 322 | 323 | IMooniswap(address(poolToken)).withdraw( 324 | amount, 325 | new uint256[](0) 326 | ); 327 | 328 | uint256[] memory dist = new uint256[](distribution.length); 329 | for (uint i = 0; i < 2; i++) { 330 | 331 | if (toToken.eq(tokens[i])) { 332 | continue; 333 | } 334 | 335 | for (uint j = 0; j < distribution.length; j++) { 336 | dist[j] = (distribution[j] >> (i * 8)) & 0xFF; 337 | } 338 | 339 | super._swap( 340 | tokens[i], 341 | toToken, 342 | tokens[i].universalBalanceOf(address(this)), 343 | dist, 344 | flags 345 | ); 346 | } 347 | } 348 | 349 | function _swapToMooniswapToken( 350 | IERC20 fromToken, 351 | IERC20 poolToken, 352 | uint256 amount, 353 | uint256[] memory distribution, 354 | uint256 flags 355 | ) private { 356 | IERC20[2] memory tokens = [ 357 | IMooniswap(address(poolToken)).tokens(0), 358 | IMooniswap(address(poolToken)).tokens(1) 359 | ]; 360 | 361 | // will overwritten to liquidity amounts 362 | uint256[] memory amounts = new uint256[](2); 363 | amounts[0] = amount.div(2); 364 | amounts[1] = amount.sub(amounts[0]); 365 | uint256[] memory dist = new uint256[](distribution.length); 366 | for (uint i = 0; i < 2; i++) { 367 | 368 | if (fromToken.eq(tokens[i])) { 369 | continue; 370 | } 371 | 372 | for (uint j = 0; j < distribution.length; j++) { 373 | dist[j] = (distribution[j] >> (i * 8)) & 0xFF; 374 | } 375 | 376 | super._swap( 377 | fromToken, 378 | tokens[i], 379 | amounts[i], 380 | dist, 381 | flags 382 | ); 383 | 384 | amounts[i] = tokens[i].universalBalanceOf(address(this)); 385 | tokens[i].universalApprove(address(poolToken), amounts[i]); 386 | } 387 | 388 | uint256 ethValue = (tokens[0].isETH() ? amounts[0] : 0) + (tokens[1].isETH() ? amounts[1] : 0); 389 | IMooniswap(address(poolToken)).deposit.value(ethValue)( 390 | amounts, 391 | new uint256[](2) 392 | ); 393 | 394 | for (uint i = 0; i < 2; i++) { 395 | tokens[i].universalTransfer( 396 | msg.sender, 397 | tokens[i].universalBalanceOf(address(this)) 398 | ); 399 | } 400 | } 401 | } 402 | -------------------------------------------------------------------------------- /contracts/OneSplitWeth.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./interface/ICompound.sol"; 4 | import "./OneSplitBase.sol"; 5 | 6 | 7 | contract OneSplitWethView is OneSplitViewWrapBase { 8 | function getExpectedReturnWithGas( 9 | IERC20 fromToken, 10 | IERC20 destToken, 11 | uint256 amount, 12 | uint256 parts, 13 | uint256 flags, 14 | uint256 destTokenEthPriceTimesGasPrice 15 | ) 16 | public 17 | view 18 | returns( 19 | uint256 returnAmount, 20 | uint256 estimateGasAmount, 21 | uint256[] memory distribution 22 | ) 23 | { 24 | return _wethGetExpectedReturn( 25 | fromToken, 26 | destToken, 27 | amount, 28 | parts, 29 | flags, 30 | destTokenEthPriceTimesGasPrice 31 | ); 32 | } 33 | 34 | function _wethGetExpectedReturn( 35 | IERC20 fromToken, 36 | IERC20 destToken, 37 | uint256 amount, 38 | uint256 parts, 39 | uint256 flags, 40 | uint256 destTokenEthPriceTimesGasPrice 41 | ) 42 | private 43 | view 44 | returns( 45 | uint256 returnAmount, 46 | uint256 estimateGasAmount, 47 | uint256[] memory distribution 48 | ) 49 | { 50 | if (fromToken == destToken) { 51 | return (amount, 0, new uint256[](DEXES_COUNT)); 52 | } 53 | 54 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_WETH)) { 55 | if (fromToken == weth || fromToken == bancorEtherToken) { 56 | return super.getExpectedReturnWithGas(ETH_ADDRESS, destToken, amount, parts, flags, destTokenEthPriceTimesGasPrice); 57 | } 58 | 59 | if (destToken == weth || destToken == bancorEtherToken) { 60 | return super.getExpectedReturnWithGas(fromToken, ETH_ADDRESS, amount, parts, flags, destTokenEthPriceTimesGasPrice); 61 | } 62 | } 63 | 64 | return super.getExpectedReturnWithGas( 65 | fromToken, 66 | destToken, 67 | amount, 68 | parts, 69 | flags, 70 | destTokenEthPriceTimesGasPrice 71 | ); 72 | } 73 | } 74 | 75 | 76 | contract OneSplitWeth is OneSplitBaseWrap { 77 | function _swap( 78 | IERC20 fromToken, 79 | IERC20 destToken, 80 | uint256 amount, 81 | uint256[] memory distribution, 82 | uint256 flags 83 | ) internal { 84 | _wethSwap( 85 | fromToken, 86 | destToken, 87 | amount, 88 | distribution, 89 | flags 90 | ); 91 | } 92 | 93 | function _wethSwap( 94 | IERC20 fromToken, 95 | IERC20 destToken, 96 | uint256 amount, 97 | uint256[] memory distribution, 98 | uint256 flags 99 | ) private { 100 | if (fromToken == destToken) { 101 | return; 102 | } 103 | 104 | if (flags.check(FLAG_DISABLE_ALL_WRAP_SOURCES) == flags.check(FLAG_DISABLE_WETH)) { 105 | if (fromToken == weth) { 106 | weth.withdraw(weth.balanceOf(address(this))); 107 | super._swap( 108 | ETH_ADDRESS, 109 | destToken, 110 | amount, 111 | distribution, 112 | flags 113 | ); 114 | return; 115 | } 116 | 117 | if (fromToken == bancorEtherToken) { 118 | bancorEtherToken.withdraw(bancorEtherToken.balanceOf(address(this))); 119 | super._swap( 120 | ETH_ADDRESS, 121 | destToken, 122 | amount, 123 | distribution, 124 | flags 125 | ); 126 | return; 127 | } 128 | 129 | if (destToken == weth) { 130 | _wethSwap( 131 | fromToken, 132 | ETH_ADDRESS, 133 | amount, 134 | distribution, 135 | flags 136 | ); 137 | weth.deposit.value(address(this).balance)(); 138 | return; 139 | } 140 | 141 | if (destToken == bancorEtherToken) { 142 | _wethSwap( 143 | fromToken, 144 | ETH_ADDRESS, 145 | amount, 146 | distribution, 147 | flags 148 | ); 149 | bancorEtherToken.deposit.value(address(this).balance)(); 150 | return; 151 | } 152 | } 153 | 154 | return super._swap( 155 | fromToken, 156 | destToken, 157 | amount, 158 | distribution, 159 | flags 160 | ); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /contracts/UniversalERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 6 | 7 | 8 | library UniversalERC20 { 9 | 10 | using SafeMath for uint256; 11 | using SafeERC20 for IERC20; 12 | 13 | IERC20 private constant ZERO_ADDRESS = IERC20(0x0000000000000000000000000000000000000000); 14 | IERC20 private constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); 15 | 16 | function universalTransfer(IERC20 token, address to, uint256 amount) internal returns(bool) { 17 | if (amount == 0) { 18 | return true; 19 | } 20 | 21 | if (isETH(token)) { 22 | address(uint160(to)).transfer(amount); 23 | } else { 24 | token.safeTransfer(to, amount); 25 | return true; 26 | } 27 | } 28 | 29 | function universalTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { 30 | if (amount == 0) { 31 | return; 32 | } 33 | 34 | if (isETH(token)) { 35 | require(from == msg.sender && msg.value >= amount, "Wrong useage of ETH.universalTransferFrom()"); 36 | if (to != address(this)) { 37 | address(uint160(to)).transfer(amount); 38 | } 39 | if (msg.value > amount) { 40 | msg.sender.transfer(msg.value.sub(amount)); 41 | } 42 | } else { 43 | token.safeTransferFrom(from, to, amount); 44 | } 45 | } 46 | 47 | function universalTransferFromSenderToThis(IERC20 token, uint256 amount) internal { 48 | if (amount == 0) { 49 | return; 50 | } 51 | 52 | if (isETH(token)) { 53 | if (msg.value > amount) { 54 | // Return remainder if exist 55 | msg.sender.transfer(msg.value.sub(amount)); 56 | } 57 | } else { 58 | token.safeTransferFrom(msg.sender, address(this), amount); 59 | } 60 | } 61 | 62 | function universalApprove(IERC20 token, address to, uint256 amount) internal { 63 | if (!isETH(token)) { 64 | if (amount == 0) { 65 | token.safeApprove(to, 0); 66 | return; 67 | } 68 | 69 | uint256 allowance = token.allowance(address(this), to); 70 | if (allowance < amount) { 71 | if (allowance > 0) { 72 | token.safeApprove(to, 0); 73 | } 74 | token.safeApprove(to, amount); 75 | } 76 | } 77 | } 78 | 79 | function universalBalanceOf(IERC20 token, address who) internal view returns (uint256) { 80 | if (isETH(token)) { 81 | return who.balance; 82 | } else { 83 | return token.balanceOf(who); 84 | } 85 | } 86 | 87 | function universalDecimals(IERC20 token) internal view returns (uint256) { 88 | 89 | if (isETH(token)) { 90 | return 18; 91 | } 92 | 93 | (bool success, bytes memory data) = address(token).staticcall.gas(10000)( 94 | abi.encodeWithSignature("decimals()") 95 | ); 96 | if (!success || data.length == 0) { 97 | (success, data) = address(token).staticcall.gas(10000)( 98 | abi.encodeWithSignature("DECIMALS()") 99 | ); 100 | } 101 | 102 | return (success && data.length > 0) ? abi.decode(data, (uint256)) : 18; 103 | } 104 | 105 | function isETH(IERC20 token) internal pure returns(bool) { 106 | return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS)); 107 | } 108 | 109 | function eq(IERC20 a, IERC20 b) internal pure returns(bool) { 110 | return a == b || (isETH(a) && isETH(b)); 111 | } 112 | 113 | function notExist(IERC20 token) internal pure returns(bool) { 114 | return (address(token) == address(-1)); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /contracts/interface/IAaveRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "./IAaveToken.sol"; 5 | 6 | 7 | contract IAaveRegistry { 8 | function tokenByAToken(IAaveToken aToken) external view returns(IERC20); 9 | function aTokenByToken(IERC20 token) external view returns(IAaveToken); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IAaveToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IAaveToken is IERC20 { 7 | function underlyingAssetAddress() external view returns (IERC20); 8 | 9 | function redeem(uint256 amount) external; 10 | } 11 | 12 | 13 | interface IAaveLendingPool { 14 | function core() external view returns (address); 15 | 16 | function deposit(IERC20 token, uint256 amount, uint16 refCode) external payable; 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interface/IBalancerPool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IBalancerPool { 7 | function getSwapFee() 8 | external view returns (uint256 balance); 9 | 10 | function getDenormalizedWeight(IERC20 token) 11 | external view returns (uint256 balance); 12 | 13 | function getBalance(IERC20 token) 14 | external view returns (uint256 balance); 15 | 16 | function swapExactAmountIn( 17 | IERC20 tokenIn, 18 | uint256 tokenAmountIn, 19 | IERC20 tokenOut, 20 | uint256 minAmountOut, 21 | uint256 maxPrice 22 | ) 23 | external 24 | returns (uint256 tokenAmountOut, uint256 spotPriceAfter); 25 | } 26 | 27 | 28 | // 0xA961672E8Db773be387e775bc4937C678F3ddF9a 29 | interface IBalancerHelper { 30 | function getReturns( 31 | IBalancerPool pool, 32 | IERC20 fromToken, 33 | IERC20 destToken, 34 | uint256[] calldata amounts 35 | ) 36 | external 37 | view 38 | returns(uint256[] memory rets); 39 | } 40 | -------------------------------------------------------------------------------- /contracts/interface/IBalancerRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "./IBalancerPool.sol"; 5 | 6 | 7 | interface IBalancerRegistry { 8 | event PoolAdded( 9 | address indexed pool 10 | ); 11 | event PoolTokenPairAdded( 12 | address indexed pool, 13 | address indexed fromToken, 14 | address indexed destToken 15 | ); 16 | event IndicesUpdated( 17 | address indexed fromToken, 18 | address indexed destToken, 19 | bytes32 oldIndices, 20 | bytes32 newIndices 21 | ); 22 | 23 | // Get info about pool pair for 1 SLOAD 24 | function getPairInfo(address pool, address fromToken, address destToken) 25 | external view returns(uint256 weight1, uint256 weight2, uint256 swapFee); 26 | 27 | // Pools 28 | function checkAddedPools(address pool) 29 | external view returns(bool); 30 | function getAddedPoolsLength() 31 | external view returns(uint256); 32 | function getAddedPools() 33 | external view returns(address[] memory); 34 | function getAddedPoolsWithLimit(uint256 offset, uint256 limit) 35 | external view returns(address[] memory result); 36 | 37 | // Tokens 38 | function getAllTokensLength() 39 | external view returns(uint256); 40 | function getAllTokens() 41 | external view returns(address[] memory); 42 | function getAllTokensWithLimit(uint256 offset, uint256 limit) 43 | external view returns(address[] memory result); 44 | 45 | // Pairs 46 | function getPoolsLength(address fromToken, address destToken) 47 | external view returns(uint256); 48 | function getPools(address fromToken, address destToken) 49 | external view returns(address[] memory); 50 | function getPoolsWithLimit(address fromToken, address destToken, uint256 offset, uint256 limit) 51 | external view returns(address[] memory result); 52 | function getBestPools(address fromToken, address destToken) 53 | external view returns(address[] memory pools); 54 | function getBestPoolsWithLimit(address fromToken, address destToken, uint256 limit) 55 | external view returns(address[] memory pools); 56 | 57 | // Get swap rates 58 | function getPoolReturn(address pool, address fromToken, address destToken, uint256 amount) 59 | external view returns(uint256); 60 | function getPoolReturns(address pool, address fromToken, address destToken, uint256[] calldata amounts) 61 | external view returns(uint256[] memory result); 62 | 63 | // Add and update registry 64 | function addPool(address pool) external returns(uint256 listed); 65 | function addPools(address[] calldata pools) external returns(uint256[] memory listed); 66 | function updatedIndices(address[] calldata tokens, uint256 lengthLimit) external; 67 | } 68 | -------------------------------------------------------------------------------- /contracts/interface/IBancorContractRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | contract IBancorContractRegistry { 5 | function addressOf(bytes32 contractName) external view returns (address); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interface/IBancorConverterRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IBancorConverterRegistry { 7 | 8 | function getConvertibleTokenSmartTokenCount(IERC20 convertibleToken) 9 | external view returns(uint256); 10 | 11 | function getConvertibleTokenSmartTokens(IERC20 convertibleToken) 12 | external view returns(address[] memory); 13 | 14 | function getConvertibleTokenSmartToken(IERC20 convertibleToken, uint256 index) 15 | external view returns(address); 16 | 17 | function isConvertibleTokenSmartToken(IERC20 convertibleToken, address value) 18 | external view returns(bool); 19 | } 20 | -------------------------------------------------------------------------------- /contracts/interface/IBancorEtherToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IBancorEtherToken is IERC20 { 7 | function deposit() external payable; 8 | 9 | function withdraw(uint256 amount) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IBancorFinder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IBancorFinder { 7 | function buildBancorPath( 8 | IERC20 fromToken, 9 | IERC20 destToken 10 | ) 11 | external 12 | view 13 | returns(address[] memory path); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interface/IBancorNetwork.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | interface IBancorNetwork { 5 | function getReturnByPath(address[] calldata path, uint256 amount) 6 | external 7 | view 8 | returns (uint256 returnAmount, uint256 conversionFee); 9 | 10 | function claimAndConvert(address[] calldata path, uint256 amount, uint256 minReturn) 11 | external 12 | returns (uint256); 13 | 14 | function convert(address[] calldata path, uint256 amount, uint256 minReturn) 15 | external 16 | payable 17 | returns (uint256); 18 | } 19 | -------------------------------------------------------------------------------- /contracts/interface/IBancorNetworkPathFinder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IBancorNetworkPathFinder { 7 | function generatePath(IERC20 sourceToken, IERC20 targetToken) 8 | external 9 | view 10 | returns (address[] memory); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interface/IBdai.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IBdai is IERC20 { 7 | function join(uint256) external; 8 | 9 | function exit(uint256) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IChai.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IPot { 7 | function dsr() external view returns (uint256); 8 | 9 | function chi() external view returns (uint256); 10 | 11 | function rho() external view returns (uint256); 12 | 13 | function drip() external returns (uint256); 14 | 15 | function join(uint256) external; 16 | 17 | function exit(uint256) external; 18 | } 19 | 20 | 21 | contract IChai is IERC20 { 22 | function POT() public view returns (IPot); 23 | 24 | function join(address dst, uint256 wad) external; 25 | 26 | function exit(address src, uint256 wad) external; 27 | } 28 | 29 | 30 | library ChaiHelper { 31 | IPot private constant POT = IPot(0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7); 32 | uint256 private constant RAY = 10**27; 33 | 34 | function _mul(uint256 x, uint256 y) private pure returns (uint256 z) { 35 | require(y == 0 || (z = x * y) / y == x); 36 | } 37 | 38 | function _rmul(uint256 x, uint256 y) private pure returns (uint256 z) { 39 | // always rounds down 40 | z = _mul(x, y) / RAY; 41 | } 42 | 43 | function _rdiv(uint256 x, uint256 y) private pure returns (uint256 z) { 44 | // always rounds down 45 | z = _mul(x, RAY) / y; 46 | } 47 | 48 | function rpow(uint256 x, uint256 n, uint256 base) private pure returns (uint256 z) { 49 | // solium-disable-next-line security/no-inline-assembly 50 | assembly { 51 | switch x 52 | case 0 { 53 | switch n 54 | case 0 { 55 | z := base 56 | } 57 | default { 58 | z := 0 59 | } 60 | } 61 | default { 62 | switch mod(n, 2) 63 | case 0 { 64 | z := base 65 | } 66 | default { 67 | z := x 68 | } 69 | let half := div(base, 2) // for rounding. 70 | for { 71 | n := div(n, 2) 72 | } n { 73 | n := div(n, 2) 74 | } { 75 | let xx := mul(x, x) 76 | if iszero(eq(div(xx, x), x)) { 77 | revert(0, 0) 78 | } 79 | let xxRound := add(xx, half) 80 | if lt(xxRound, xx) { 81 | revert(0, 0) 82 | } 83 | x := div(xxRound, base) 84 | if mod(n, 2) { 85 | let zx := mul(z, x) 86 | if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { 87 | revert(0, 0) 88 | } 89 | let zxRound := add(zx, half) 90 | if lt(zxRound, zx) { 91 | revert(0, 0) 92 | } 93 | z := div(zxRound, base) 94 | } 95 | } 96 | } 97 | } 98 | } 99 | 100 | function potDrip() private view returns (uint256) { 101 | return _rmul(rpow(POT.dsr(), now - POT.rho(), RAY), POT.chi()); 102 | } 103 | 104 | function chaiPrice(IChai chai) internal view returns(uint256) { 105 | return chaiToDai(chai, 1e18); 106 | } 107 | 108 | function daiToChai( 109 | IChai /*chai*/, 110 | uint256 amount 111 | ) internal view returns (uint256) { 112 | uint256 chi = (now > POT.rho()) ? potDrip() : POT.chi(); 113 | return _rdiv(amount, chi); 114 | } 115 | 116 | function chaiToDai( 117 | IChai /*chai*/, 118 | uint256 amount 119 | ) internal view returns (uint256) { 120 | uint256 chi = (now > POT.rho()) ? potDrip() : POT.chi(); 121 | return _rmul(chi, amount); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /contracts/interface/ICompound.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract ICompound { 7 | function markets(address cToken) 8 | external 9 | view 10 | returns (bool isListed, uint256 collateralFactorMantissa); 11 | } 12 | 13 | 14 | contract ICompoundToken is IERC20 { 15 | function underlying() external view returns (address); 16 | 17 | function exchangeRateStored() external view returns (uint256); 18 | 19 | function mint(uint256 mintAmount) external returns (uint256); 20 | 21 | function redeem(uint256 redeemTokens) external returns (uint256); 22 | } 23 | 24 | 25 | contract ICompoundEther is IERC20 { 26 | function mint() external payable; 27 | 28 | function redeem(uint256 redeemTokens) external returns (uint256); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/interface/ICompoundRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "./ICompound.sol"; 5 | 6 | 7 | contract ICompoundRegistry { 8 | function tokenByCToken(ICompoundToken cToken) external view returns(IERC20); 9 | function cTokenByToken(IERC20 token) external view returns(ICompoundToken); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/ICurve.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | interface ICurve { 5 | // solium-disable-next-line mixedcase 6 | function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns(uint256 dy); 7 | 8 | // solium-disable-next-line mixedcase 9 | function get_dy(int128 i, int128 j, uint256 dx) external view returns(uint256 dy); 10 | 11 | // solium-disable-next-line mixedcase 12 | function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 minDy) external; 13 | 14 | // solium-disable-next-line mixedcase 15 | function exchange(int128 i, int128 j, uint256 dx, uint256 minDy) external; 16 | } 17 | 18 | 19 | contract ICurveRegistry { 20 | function get_pool_info(address pool) 21 | external 22 | view 23 | returns( 24 | uint256[8] memory balances, 25 | uint256[8] memory underlying_balances, 26 | uint256[8] memory decimals, 27 | uint256[8] memory underlying_decimals, 28 | address lp_token, 29 | uint256 A, 30 | uint256 fee 31 | ); 32 | } 33 | 34 | 35 | contract ICurveCalculator { 36 | function get_dy( 37 | int128 nCoins, 38 | uint256[8] calldata balances, 39 | uint256 amp, 40 | uint256 fee, 41 | uint256[8] calldata rates, 42 | uint256[8] calldata precisions, 43 | bool underlying, 44 | int128 i, 45 | int128 j, 46 | uint256[100] calldata dx 47 | ) external view returns(uint256[100] memory dy); 48 | } 49 | -------------------------------------------------------------------------------- /contracts/interface/IDForceSwap.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IDForceSwap { 7 | function getAmountByInput(IERC20 input, IERC20 output, uint256 amount) external view returns(uint256); 8 | function swap(IERC20 input, IERC20 output, uint256 amount) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/interface/IDMM.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IDMMController { 7 | function getUnderlyingTokenForDmm(IERC20 token) external view returns(IERC20); 8 | } 9 | 10 | 11 | contract IDMM is IERC20 { 12 | function getCurrentExchangeRate() public view returns(uint256); 13 | function mint(uint256 underlyingAmount) public returns(uint256); 14 | function redeem(uint256 amount) public returns(uint256); 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interface/IFulcrum.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IFulcrumToken is IERC20 { 7 | function tokenPrice() external view returns (uint256); 8 | 9 | function loanTokenAddress() external view returns (address); 10 | 11 | function mintWithEther(address receiver) external payable returns (uint256 mintAmount); 12 | 13 | function mint(address receiver, uint256 depositAmount) external returns (uint256 mintAmount); 14 | 15 | function burnToEther(address receiver, uint256 burnAmount) 16 | external 17 | returns (uint256 loanAmountPaid); 18 | 19 | function burn(address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interface/IIdle.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IIdle is IERC20 { 7 | function token() 8 | external view returns (IERC20); 9 | 10 | function tokenPrice() 11 | external view returns (uint256); 12 | 13 | function mintIdleToken(uint256 _amount, uint256[] calldata _clientProtocolAmounts) 14 | external returns (uint256 mintedTokens); 15 | 16 | function redeemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata _clientProtocolAmounts) 17 | external returns (uint256 redeemedTokens); 18 | } 19 | -------------------------------------------------------------------------------- /contracts/interface/IIearn.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IIearn is IERC20 { 7 | function token() external view returns(IERC20); 8 | 9 | function calcPoolValueInToken() external view returns(uint256); 10 | 11 | function deposit(uint256 _amount) external; 12 | 13 | function withdraw(uint256 _shares) external; 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interface/IKyberHintHandler.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IKyberHintHandler { 7 | enum TradeType { 8 | BestOfAll, 9 | MaskIn, 10 | MaskOut, 11 | Split 12 | } 13 | 14 | function buildTokenToEthHint( 15 | IERC20 tokenSrc, 16 | TradeType tokenToEthType, 17 | bytes32[] calldata tokenToEthReserveIds, 18 | uint256[] calldata tokenToEthSplits 19 | ) external view returns (bytes memory hint); 20 | 21 | function buildEthToTokenHint( 22 | IERC20 tokenDest, 23 | TradeType ethToTokenType, 24 | bytes32[] calldata ethToTokenReserveIds, 25 | uint256[] calldata ethToTokenSplits 26 | ) external view returns (bytes memory hint); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interface/IKyberNetworkContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IKyberNetworkContract { 7 | function searchBestRate(IERC20 src, IERC20 dest, uint256 srcAmount, bool usePermissionless) 8 | external 9 | view 10 | returns (address reserve, uint256 rate); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interface/IKyberNetworkProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IKyberNetworkContract.sol"; 4 | 5 | 6 | interface IKyberNetworkProxy { 7 | function getExpectedRateAfterFee( 8 | IERC20 src, 9 | IERC20 dest, 10 | uint256 srcQty, 11 | uint256 platformFeeBps, 12 | bytes calldata hint 13 | ) external view returns (uint256 expectedRate); 14 | 15 | function tradeWithHintAndFee( 16 | IERC20 src, 17 | uint256 srcAmount, 18 | IERC20 dest, 19 | address payable destAddress, 20 | uint256 maxDestAmount, 21 | uint256 minConversionRate, 22 | address payable platformWallet, 23 | uint256 platformFeeBps, 24 | bytes calldata hint 25 | ) external payable returns (uint256 destAmount); 26 | 27 | function kyberNetworkContract() external view returns (IKyberNetworkContract); 28 | 29 | // TODO: Limit usage by tx.gasPrice 30 | // function maxGasPrice() external view returns (uint256); 31 | 32 | // TODO: Limit usage by user cap 33 | // function getUserCapInWei(address user) external view returns (uint256); 34 | // function getUserCapInTokenWei(address user, IERC20 token) external view returns (uint256); 35 | } 36 | -------------------------------------------------------------------------------- /contracts/interface/IKyberOasisReserve.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | interface IKyberOasisReserve { 5 | function otc() external view returns (address); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interface/IKyberStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IKyberStorage { 7 | function getReserveIdsPerTokenSrc( 8 | IERC20 token 9 | ) external view returns (bytes32[] memory); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IMStable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IMStable is IERC20 { 7 | function getSwapOutput( 8 | IERC20 _input, 9 | IERC20 _output, 10 | uint256 _quantity 11 | ) 12 | external 13 | view 14 | returns (bool, string memory, uint256 output); 15 | 16 | function swap( 17 | IERC20 _input, 18 | IERC20 _output, 19 | uint256 _quantity, 20 | address _recipient 21 | ) 22 | external 23 | returns (uint256 output); 24 | 25 | function redeem( 26 | IERC20 _basset, 27 | uint256 _bassetQuantity 28 | ) 29 | external 30 | returns (uint256 massetRedeemed); 31 | } 32 | 33 | interface IMassetValidationHelper { 34 | /** 35 | * @dev Returns a valid bAsset to redeem 36 | * @param _mAsset Masset addr 37 | * @return valid bool 38 | * @return string message 39 | * @return address of bAsset to redeem 40 | */ 41 | function suggestRedeemAsset( 42 | IERC20 _mAsset 43 | ) 44 | external 45 | view 46 | returns ( 47 | bool valid, 48 | string memory err, 49 | address token 50 | ); 51 | 52 | /** 53 | * @dev Returns a valid bAsset with which to mint 54 | * @param _mAsset Masset addr 55 | * @return valid bool 56 | * @return string message 57 | * @return address of bAsset to mint 58 | */ 59 | function suggestMintAsset( 60 | IERC20 _mAsset 61 | ) 62 | external 63 | view 64 | returns ( 65 | bool valid, 66 | string memory err, 67 | address token 68 | ); 69 | 70 | /** 71 | * @dev Determines if a given Redemption is valid 72 | * @param _mAsset Address of the given mAsset (e.g. mUSD) 73 | * @param _mAssetQuantity Amount of mAsset to redeem (in mUSD units) 74 | * @param _outputBasset Desired output bAsset 75 | * @return valid 76 | * @return validity reason 77 | * @return output in bAsset units 78 | * @return bAssetQuantityArg - required input argument to the 'redeem' call 79 | */ 80 | function getRedeemValidity( 81 | IERC20 _mAsset, 82 | uint256 _mAssetQuantity, 83 | IERC20 _outputBasset 84 | ) 85 | external 86 | view 87 | returns ( 88 | bool valid, 89 | string memory, 90 | uint256 output, 91 | uint256 bassetQuantityArg 92 | ); 93 | } 94 | -------------------------------------------------------------------------------- /contracts/interface/IMooniswap.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IMooniswapRegistry { 7 | function pools(IERC20 token1, IERC20 token2) external view returns(IMooniswap); 8 | function isPool(address addr) external view returns(bool); 9 | } 10 | 11 | 12 | interface IMooniswap { 13 | function fee() external view returns (uint256); 14 | 15 | function tokens(uint256 i) external view returns (IERC20); 16 | 17 | function deposit(uint256[] calldata amounts, uint256[] calldata minAmounts) external payable returns(uint256 fairSupply); 18 | 19 | function withdraw(uint256 amount, uint256[] calldata minReturns) external; 20 | 21 | function getBalanceForAddition(IERC20 token) external view returns(uint256); 22 | 23 | function getBalanceForRemoval(IERC20 token) external view returns(uint256); 24 | 25 | function getReturn( 26 | IERC20 fromToken, 27 | IERC20 destToken, 28 | uint256 amount 29 | ) 30 | external 31 | view 32 | returns(uint256 returnAmount); 33 | 34 | function swap( 35 | IERC20 fromToken, 36 | IERC20 destToken, 37 | uint256 amount, 38 | uint256 minReturn, 39 | address referral 40 | ) 41 | external 42 | payable 43 | returns(uint256 returnAmount); 44 | } 45 | -------------------------------------------------------------------------------- /contracts/interface/IOasisExchange.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IOasisExchange { 7 | function getBuyAmount(IERC20 buyGem, IERC20 payGem, uint256 payAmt) 8 | external 9 | view 10 | returns (uint256 fillAmt); 11 | 12 | function sellAllAmount(IERC20 payGem, uint256 payAmt, IERC20 buyGem, uint256 minFillAmount) 13 | external 14 | returns (uint256 fillAmt); 15 | } 16 | -------------------------------------------------------------------------------- /contracts/interface/IShell.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | interface IShell { 5 | function viewOriginTrade( 6 | address origin, 7 | address target, 8 | uint256 originAmount 9 | ) external view returns (uint256); 10 | 11 | function swapByOrigin( 12 | address origin, 13 | address target, 14 | uint256 originAmount, 15 | uint256 minTargetAmount, 16 | uint256 deadline 17 | ) external returns (uint256); 18 | } 19 | -------------------------------------------------------------------------------- /contracts/interface/ISmartToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "./ISmartTokenConverter.sol"; 5 | 6 | 7 | interface ISmartToken { 8 | function owner() external view returns (ISmartTokenConverter); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/interface/ISmartTokenConverter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface ISmartTokenConverter { 7 | function getReserveRatio(IERC20 token) external view returns (uint32); 8 | 9 | function connectorTokenCount() external view returns (uint256); 10 | 11 | function connectorTokens(uint256 i) external view returns (IERC20); 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interface/ISmartTokenFormula.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface ISmartTokenFormula { 7 | function calculateLiquidateReturn( 8 | uint256 supply, 9 | uint256 reserveBalance, 10 | uint32 totalRatio, 11 | uint256 amount 12 | ) external view returns (uint256); 13 | 14 | function calculatePurchaseReturn( 15 | uint256 supply, 16 | uint256 reserveBalance, 17 | uint32 totalRatio, 18 | uint256 amount 19 | ) external view returns (uint256); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interface/ISmartTokenRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface ISmartTokenRegistry { 7 | function isSmartToken(IERC20 token) external view returns (bool); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IUniswapExchange.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | interface IUniswapExchange { 7 | function getEthToTokenInputPrice(uint256 ethSold) external view returns (uint256 tokensBought); 8 | 9 | function getTokenToEthInputPrice(uint256 tokensSold) external view returns (uint256 ethBought); 10 | 11 | function ethToTokenSwapInput(uint256 minTokens, uint256 deadline) 12 | external 13 | payable 14 | returns (uint256 tokensBought); 15 | 16 | function tokenToEthSwapInput(uint256 tokensSold, uint256 minEth, uint256 deadline) 17 | external 18 | returns (uint256 ethBought); 19 | 20 | function tokenToTokenSwapInput( 21 | uint256 tokensSold, 22 | uint256 minTokensBought, 23 | uint256 minEthBought, 24 | uint256 deadline, 25 | address tokenAddr 26 | ) external returns (uint256 tokensBought); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interface/IUniswapFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IUniswapExchange.sol"; 4 | 5 | 6 | interface IUniswapFactory { 7 | function getExchange(IERC20 token) external view returns (IUniswapExchange exchange); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IUniswapV2Exchange.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/math/Math.sol"; 4 | import "@openzeppelin/contracts/math/SafeMath.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "../UniversalERC20.sol"; 7 | 8 | 9 | interface IUniswapV2Exchange { 10 | function getReserves() external view returns(uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast); 11 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 12 | function skim(address to) external; 13 | function sync() external; 14 | } 15 | 16 | 17 | library UniswapV2ExchangeLib { 18 | using Math for uint256; 19 | using SafeMath for uint256; 20 | using UniversalERC20 for IERC20; 21 | 22 | function getReturn( 23 | IUniswapV2Exchange exchange, 24 | IERC20 fromToken, 25 | IERC20 destToken, 26 | uint amountIn 27 | ) internal view returns (uint256 result, bool needSync, bool needSkim) { 28 | uint256 reserveIn = fromToken.universalBalanceOf(address(exchange)); 29 | uint256 reserveOut = destToken.universalBalanceOf(address(exchange)); 30 | (uint112 reserve0, uint112 reserve1,) = exchange.getReserves(); 31 | if (fromToken > destToken) { 32 | (reserve0, reserve1) = (reserve1, reserve0); 33 | } 34 | needSync = (reserveIn < reserve0 || reserveOut < reserve1); 35 | needSkim = !needSync && (reserveIn > reserve0 || reserveOut > reserve1); 36 | 37 | uint256 amountInWithFee = amountIn.mul(997); 38 | uint256 numerator = amountInWithFee.mul(Math.min(reserveOut, reserve1)); 39 | uint256 denominator = Math.min(reserveIn, reserve0).mul(1000).add(amountInWithFee); 40 | result = (denominator == 0) ? 0 : numerator.div(denominator); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/interface/IUniswapV2Factory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IUniswapV2Exchange.sol"; 4 | 5 | 6 | interface IUniswapV2Factory { 7 | function getPair(IERC20 tokenA, IERC20 tokenB) external view returns (IUniswapV2Exchange pair); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IWETH.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | 6 | contract IWETH is IERC20 { 7 | function deposit() external payable; 8 | 9 | function withdraw(uint256 amount) external; 10 | } 11 | -------------------------------------------------------------------------------- /img/howitworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1inch/1inchProtocol/811f7b69b67d1d9657e3e9c18a2e97f3e2b2b33a/img/howitworks.png -------------------------------------------------------------------------------- /img/howtouseit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1inch/1inchProtocol/811f7b69b67d1d9657e3e9c18a2e97f3e2b2b33a/img/howtouseit.png -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | // const Migrations = artifacts.require('./Migrations.sol'); 2 | // const OneSplit = artifacts.require('./OneSplit.sol'); 3 | 4 | module.exports = function (deployer) { 5 | // deployer.deploy(Migrations); 6 | // deployer.deploy(OneSplit); 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OneSplit", 3 | "version": "0.0.1", 4 | "description": "", 5 | "repository": { 6 | "type": "git", 7 | "url": "git@github.com:CryptoManiacsZone/1split.git" 8 | }, 9 | "license": "MIT", 10 | "dependencies": { 11 | "@openzeppelin/contracts": "^2.5.0" 12 | }, 13 | "devDependencies": { 14 | "chai": "^4.2.0", 15 | "coveralls": "^3.1.0", 16 | "eslint": "^7.3.1", 17 | "eslint-config-standard": "^14.1.1", 18 | "eslint-plugin-import": "^2.22.0", 19 | "eslint-plugin-node": "^11.1.0", 20 | "eslint-plugin-promise": "^4.0.1", 21 | "eslint-plugin-standard": "^4.0.0", 22 | "eth-gas-reporter": "^0.2.17", 23 | "ganache-cli": "^6.9.1", 24 | "@openzeppelin/test-helpers": "^0.5.6", 25 | "solc": "^0.5.17", 26 | "solidity-coverage": "^0.7.9", 27 | "ethlint": "^1.2.5", 28 | "truffle": "^5.1.32", 29 | "truffle-flattener": "^1.4.4" 30 | }, 31 | "scripts": { 32 | "test": "scripts/test.sh", 33 | "coverage": "scripts/coverage.sh && cat coverage/lcov.info | coveralls", 34 | "lint:js": "eslint .", 35 | "lint:js:fix": "eslint . --fix", 36 | "lint:sol": "solium -d .", 37 | "lint:sol:fix": "solium -d . --fix", 38 | "lint": "npm run lint:js && npm run lint:sol", 39 | "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", 40 | "dist": "truffle-flattener ./contracts/OneSplit.sol > OneSplit.full.sol && solcjs --bin --abi --optimize OneSplit.full.sol && mv OneSplit_full_sol_OneSplit.bin OneSplit.full.bin && mv OneSplit_full_sol_OneSplit.abi OneSplit.full.abi && rm *_sol_*", 41 | "dist:view": "truffle-flattener ./contracts/OneSplit.sol > OneSplitView.full.sol && solcjs --bin --abi OneSplitView.full.sol && mv OneSplitView_full_sol_OneSplitView.bin OneSplitView.full.bin && mv OneSplitView_full_sol_OneSplitView.abi OneSplitView.full.abi && rm *_sol_*", 42 | "dist:audit": "truffle-flattener ./contracts/OneSplitAudit.sol > OneSplitAudit.full.sol && solcjs --bin --abi --optimize OneSplitAudit.full.sol && mv OneSplitAudit_full_sol_OneSplitAudit.bin OneSplitAudit.full.bin && mv OneSplitAudit_full_sol_OneSplitAudit.abi OneSplitAudit.full.abi && rm *_sol_*", 43 | "dist:bnt": "truffle-flattener ./contracts/BancorFinder.sol > BancorFinder.full.sol && solcjs --bin --abi --optimize BancorFinder.full.sol && mv BancorFinder_full_sol_BancorFinder.bin BancorFinder.full.bin && mv BancorFinder_full_sol_BancorFinder.abi BancorFinder.full.abi && rm *_sol_*", 44 | "dist:comp": "truffle-flattener ./contracts/CompoundRegistry.sol > CompoundRegistry.full.sol && solcjs --bin --abi --optimize CompoundRegistry.full.sol && mv CompoundRegistry_full_sol_CompoundRegistry.bin CompoundRegistry.full.bin && mv CompoundRegistry_full_sol_CompoundRegistry.abi CompoundRegistry.full.abi && rm *_sol_*", 45 | "dist:bal": "truffle-flattener ./contracts/BalancerHelper.sol > BalancerHelper.full.sol && solcjs --bin --abi --optimize BalancerHelper.full.sol && mv BalancerHelper_full_sol_BalancerHelper.bin BalancerHelper.full.bin && mv BalancerHelper_full_sol_BalancerHelper.abi BalancerHelper.full.abi && rm *_sol_*", 46 | "dist:aave": "truffle-flattener ./contracts/AaveRegistry.sol > AaveRegistry.full.sol && solcjs --bin --abi --optimize AaveRegistry.full.sol && mv AaveRegistry_full_sol_AaveRegistry.bin AaveRegistry.full.bin && mv AaveRegistry_full_sol_AaveRegistry.abi AaveRegistry.full.abi && rm *_sol_*" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /scripts/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SOLIDITY_COVERAGE=true scripts/test.sh 4 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit script as soon as a command fails. 4 | set -o errexit 5 | 6 | # Executes cleanup function at script exit. 7 | trap cleanup EXIT 8 | 9 | cleanup() { 10 | # Kill the ganache instance that we started (if we started one and if it's still running). 11 | if [ -n "$ganache_pid" ] && ps -p $ganache_pid > /dev/null; then 12 | kill -9 $ganache_pid 13 | fi 14 | } 15 | 16 | if [ "$SOLIDITY_COVERAGE" = true ]; then 17 | ganache_port=8555 18 | else 19 | ganache_port=9545 20 | fi 21 | 22 | ganache_running() { 23 | nc -z localhost "$ganache_port" 24 | } 25 | 26 | start_ganache() { 27 | # We define 10 accounts with balance 1M ether, needed for high-value tests. 28 | local accounts=( 29 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,1000000000000000000000000" 30 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,1000000000000000000000000" 31 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,1000000000000000000000000" 32 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501203,1000000000000000000000000" 33 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501204,1000000000000000000000000" 34 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501205,1000000000000000000000000" 35 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501206,1000000000000000000000000" 36 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501207,1000000000000000000000000" 37 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501208,1000000000000000000000000" 38 | --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000" 39 | ) 40 | 41 | if [ "$SOLIDITY_COVERAGE" = true ]; then 42 | node_modules/.bin/testrpc-sc --gasLimit 0xfffffffffff --port "$ganache_port" "${accounts[@]}" > /dev/null & 43 | else 44 | [ -z "$ETH_NODE" ] && source .env 45 | echo "Using ETH_NODE env variable to fork Ethereum Mainnet, ensure to define it in .env file" 46 | node_modules/.bin/ganache-cli -f "$ETH_NODE" --allowUnlimitedContractSize --gasLimit 0xfffffffffff --port "$ganache_port" "${accounts[@]}" > /dev/null & 47 | fi 48 | 49 | ganache_pid=$! 50 | } 51 | 52 | if ganache_running; then 53 | echo "Using existing ganache instance" 54 | else 55 | echo "Starting our own ganache instance" 56 | start_ganache 57 | fi 58 | 59 | if [ "$SOLC_NIGHTLY" = true ]; then 60 | echo "Downloading solc nightly" 61 | wget -q https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/soljson-nightly.js -O /tmp/soljson.js && find . -name soljson.js -exec cp /tmp/soljson.js {} \; 62 | fi 63 | 64 | truffle version 65 | 66 | if [ "$SOLIDITY_COVERAGE" = true ]; then 67 | node_modules/.bin/solidity-coverage 68 | 69 | if [ "$CONTINUOUS_INTEGRATION" = true ]; then 70 | cat coverage/lcov.info | node_modules/.bin/coveralls 71 | fi 72 | else 73 | yarn truffle test --stacktrace "$@" 74 | fi 75 | -------------------------------------------------------------------------------- /solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["solhint:recommended"], 3 | "rules": { 4 | "prettier/prettier": "error", 5 | "avoid-throw": false, 6 | "avoid-suicide": "error", 7 | "avoid-sha3": "warn" 8 | }, 9 | "plugins": ["prettier"] 10 | } 11 | -------------------------------------------------------------------------------- /test/OneSplit.js: -------------------------------------------------------------------------------- 1 | const { BN, ether, expectRevert } = require('@openzeppelin/test-helpers'); 2 | const { expect } = require('chai'); 3 | const assert = require('assert'); 4 | 5 | const OneSplitView = artifacts.require('OneSplitView'); 6 | const OneSplitViewWrap = artifacts.require('OneSplitViewWrap'); 7 | const OneSplit = artifacts.require('OneSplit'); 8 | const OneSplitWrap = artifacts.require('OneSplitWrap'); 9 | const IMooniswapRegistry = artifacts.require('IMooniswapRegistry'); 10 | const IMooniswap = artifacts.require('IMooniswap'); 11 | 12 | const DISABLE_ALL = new BN('20000000', 16).add(new BN('40000000', 16)); 13 | const CURVE_SYNTHETIX = new BN('40000', 16); 14 | const CURVE_COMPOUND = new BN('1000', 16); 15 | const CURVE_ALL = new BN('200000000000', 16); 16 | const KYBER_ALL = new BN('200000000000000', 16); 17 | const MOONISWAP_ALL = new BN('8000000000000000', 16); 18 | const BALANCER_ALL = new BN('1000000000000', 16); 19 | 20 | contract('OneSplit', function ([_, addr1]) { 21 | describe('OneSplit', async function () { 22 | before(async function () { 23 | // let mr = await IMooniswapRegistry.at('0xEa579905818Ae70051C057e5E6aF3A5dC85745A4'); 24 | // let addr = await mr.pools('0x0000000000000000000000000000000000000000', '0x6B175474E89094C44Da98b954EedeAC495271d0F'); 25 | // let p = await IMooniswap.at(addr); 26 | // console.log('p.address', addr); 27 | // console.log('add', await p.getBalanceForAddition('0x0000000000000000000000000000000000000000')); 28 | // console.log('rem', await p.getBalanceForRemoval('0x6B175474E89094C44Da98b954EedeAC495271d0F')); 29 | 30 | // exit(1); 31 | this.subSplitView = await OneSplitView.new(); 32 | this.splitView = await OneSplitViewWrap.new(this.subSplitView.address); 33 | 34 | const subSplit = await OneSplit.new(this.splitView.address); 35 | this.split = await OneSplitWrap.new(this.splitView.address, subSplit.address); 36 | }); 37 | 38 | // it.only('should work with ETH => CHAI', async function () { 39 | // const res = await this.split.swap( 40 | // '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 41 | // '0x06AF07097C9Eeb7fD685c692751D5C66dB49c215', // CHAI 42 | // '100000000000000000000', // 100.0 43 | // 10, 44 | // 0, // enable all 45 | // { value: '100000000000000000000' } 46 | // ); 47 | 48 | // console.log('Swap: 100 ETH'); 49 | // console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' CHAI'); 50 | // // console.log('distribution:', res.distribution.map(a => a.toString())); 51 | // // console.log('raw:', res.returnAmount.toString()); 52 | // }); 53 | 54 | it('should work with Mooniswap ETH => DAI', async function () { 55 | const res = await this.split.getExpectedReturn( 56 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 57 | '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC 58 | '1000000000000000000', // 1.0 59 | 10, 60 | DISABLE_ALL.add(MOONISWAP_ALL), // enable only Mooniswap 61 | ); 62 | 63 | console.log('Swap: 1 ETH'); 64 | console.log('returnAmount:', res.returnAmount.toString() / 1e6 + ' USDC'); 65 | // console.log('distribution:', res.distribution.map(a => a.toString())); 66 | // console.log('raw:', res.returnAmount.toString()); 67 | expect(res.returnAmount).to.be.bignumber.above('390000000'); 68 | }); 69 | 70 | it('should work with Balancer ETH => DAI', async function () { 71 | const res = await this.split.getExpectedReturn( 72 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 73 | '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC 74 | '1000000000000000000', // 1.0 75 | 10, 76 | DISABLE_ALL.add(BALANCER_ALL), // enable only Mooniswap 77 | ); 78 | 79 | console.log('Swap: 1 ETH'); 80 | console.log('returnAmount:', res.returnAmount.toString() / 1e6 + ' USDC'); 81 | // console.log('distribution:', res.distribution.map(a => a.toString())); 82 | // console.log('raw:', res.returnAmount.toString()); 83 | expect(res.returnAmount).to.be.bignumber.above('390000000'); 84 | }); 85 | 86 | it('should work with ETH => COMP', async function () { 87 | const res = await this.split.getExpectedReturn( 88 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 89 | '0xc00e94Cb662C3520282E6f5717214004A7f26888', // USDC 90 | '1000000000000000000', // 1.0 91 | 1, 92 | 0, 93 | ); 94 | 95 | console.log('Swap: 1 ETH'); 96 | console.log('returnAmount:', res.returnAmount.toString() / 1e18 + ' COMP'); 97 | // console.log('distribution:', res.distribution.map(a => a.toString())); 98 | // console.log('raw:', res.returnAmount.toString()); 99 | expect(res.returnAmount).to.be.bignumber.above('390000000'); 100 | }); 101 | 102 | it('should work with Uniswap USDT => BAL', async function () { 103 | const res = await this.split.getExpectedReturn( 104 | '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT 105 | '0xba100000625a3754423978a60c9317c58a424e3D', // BAL 106 | '100000000', // 1.0 107 | 10, 108 | DISABLE_ALL.addn(1), // enable only Uniswap V1 109 | ); 110 | 111 | console.log('Swap: 1 USDT'); 112 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' BAL'); 113 | // console.log('distribution:', res.distribution.map(a => a.toString())); 114 | // console.log('raw:', res.returnAmount.toString()); 115 | expect(res.returnAmount).to.be.bignumber.equals('0'); 116 | }); 117 | 118 | it('should work with DAI => mUSD', async function () { 119 | const res = await this.split.getExpectedReturn( 120 | '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC 121 | '0xe2f2a5C287993345a840Db3B0845fbC70f5935a5', // mUSD 122 | '2000000', // 2.0 123 | 1, 124 | DISABLE_ALL.add(web3.utils.toBN('0x20000000000')), // enable only mStable mUSD 125 | ); 126 | 127 | console.log('Swap: 2 USDC'); 128 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' mUSD'); 129 | // console.log('distribution:', res.distribution.map(a => a.toString())); 130 | // console.log('raw:', res.returnAmount.toString()); 131 | expect(res.returnAmount).to.be.bignumber.equals('2000000000000000000'); 132 | }); 133 | 134 | it('should work with Bancor USDT => BAL', async function () { 135 | const res = await this.subSplitView.getExpectedReturn( 136 | '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT 137 | '0xba100000625a3754423978a60c9317c58a424e3D', // BAL 138 | '100000000', // 1.0 139 | 10, 140 | DISABLE_ALL.addn(4), // enable only Bancor 141 | ); 142 | 143 | console.log('Swap: 1 USDT'); 144 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' BAL'); 145 | // console.log('distribution:', res.distribution.map(a => a.toString())); 146 | // console.log('raw:', res.returnAmount.toString()); 147 | expect(res.returnAmount).to.be.bignumber.equals('0'); 148 | }); 149 | 150 | it('should work with Uniswap ETH => DAI', async function () { 151 | const res = await this.split.getExpectedReturn( 152 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 153 | '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI 154 | '1000000000000000000', // 1.0 155 | 10, 156 | DISABLE_ALL.addn(1), // enable only Uniswap V1 157 | ); 158 | 159 | console.log('Swap: 1 ETH'); 160 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' WBTC'); 161 | // console.log('distribution:', res.distribution.map(a => a.toString())); 162 | // console.log('raw:', res.returnAmount.toString()); 163 | expect(res.returnAmount).to.be.bignumber.above('200000000000000000000'); 164 | }); 165 | 166 | it('should work with Kyber ETH => DAI', async function () { 167 | const res = await this.split.getExpectedReturn( 168 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 169 | '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI 170 | '1000000000000000000', // 1.0 171 | 10, 172 | DISABLE_ALL.add(KYBER_ALL), // enable only Kyber 173 | ); 174 | 175 | console.log('Swap: 1 ETH'); 176 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' WBTC'); 177 | // console.log('distribution:', res.distribution.map(a => a.toString())); 178 | // console.log('raw:', res.returnAmount.toString()); 179 | expect(res.returnAmount).to.be.bignumber.above('200000000000000000000'); 180 | }); 181 | 182 | it.only('should work with Kyber ETH => USDT', async function () { 183 | const res = await this.split.getExpectedReturn( 184 | '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH 185 | '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT 186 | '50000000000000000000', // 50.0 187 | 10, 188 | DISABLE_ALL.add(KYBER_ALL), // enable only Kyber 189 | ); 190 | 191 | console.log('Swap: 1 ETH'); 192 | console.log('returnAmount:', res.returnAmount.toString() / 1e6 + ' USDT'); 193 | console.log('distribution:', res.distribution.map(a => a.toString())); 194 | // console.log('raw:', res.returnAmount.toString()); 195 | expect(res.returnAmount).to.be.bignumber.above('200000000000000000000'); 196 | }); 197 | 198 | it('should split among BTC Curves', async function () { 199 | const res = await this.split.getExpectedReturn( 200 | '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', // renBTC 201 | '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC 202 | '100000000000', // 1000.00 203 | 10, 204 | DISABLE_ALL.add(CURVE_ALL), // enable only all curves 205 | ); 206 | 207 | console.log('Swap: 100 renBTC'); 208 | console.log('returnAmount:', res.returnAmount.toString() / 1e8 + ' WBTC'); 209 | // console.log('distribution:', res.distribution.map(a => a.toString())); 210 | // console.log('raw:', res.returnAmount.toString()); 211 | expect(res.distribution.filter(r => r.gt(new BN(0))).length).to.be.equals(2); 212 | }); 213 | 214 | it('should split among USD Curves', async function () { 215 | const res = await this.split.getExpectedReturn( 216 | '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI 217 | '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC 218 | '1000000000000000000000000', // 1,000,000.00 219 | 4, 220 | DISABLE_ALL.add(CURVE_COMPOUND).add(CURVE_SYNTHETIX), // enable only all curves 221 | ); 222 | 223 | console.log('Swap: 1,000,000 DAI'); 224 | console.log('returnAmount:', res.returnAmount.toString() / 1e18 + ' USDC'); 225 | console.log('distribution:', res.distribution.map(a => a.toString())); 226 | // console.log('raw:', res.returnAmount.toString()); 227 | expect(res.distribution.filter(r => r.gt(new BN(0))).length).to.be.above(1); 228 | }); 229 | 230 | it('should work', async function () { 231 | // const tx = await this.split.getExpectedReturnMock( 232 | // '0x0000000000000000000000000000000000000000', 233 | // '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', 234 | // web3.utils.toWei('20'), 235 | // 10 236 | // ); 237 | const res = await this.split.getExpectedReturn( 238 | '0x0000000000000000000000000000000000000000', // ETH 239 | '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', // DAI 240 | web3.utils.toWei('20'), 241 | 10, 242 | 4, 243 | ); 244 | console.log('input: 20 ETH'); 245 | console.log('returnAmount:', res.returnAmount.toString() / 1e18 + ' DAI'); 246 | // console.log('distribution:', res.distribution.map(a => a.toString())); 247 | 248 | console.log('raw:', res.returnAmount.toString()); 249 | }); 250 | 251 | it('should return same input (DAI to bDAI)', async function () { 252 | const inputAmount = '84'; 253 | 254 | const res = await this.split.getExpectedReturn( 255 | '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI 256 | '0x6a4FFAafa8DD400676Df8076AD6c724867b0e2e8', // bDAI 257 | web3.utils.toWei(inputAmount), 258 | 10, 259 | 0, 260 | ); 261 | 262 | const returnAmount = web3.utils.fromWei(res.returnAmount.toString(), 'ether'); 263 | 264 | assert.strictEqual( 265 | returnAmount, 266 | inputAmount, 267 | 'Invalid swap ratio', 268 | ); 269 | 270 | console.log(`input: ${inputAmount} DAI`); 271 | console.log(`returnAmount: ${returnAmount} bDAI`); 272 | // console.log('distribution:', res.distribution.map(a => a.toString())); 273 | 274 | console.log('raw:', res.returnAmount.toString()); 275 | }); 276 | 277 | it('should return same input (bDAI to DAI)', async function () { 278 | const inputAmount = '84'; 279 | 280 | const res = await this.split.getExpectedReturn( 281 | '0x6a4FFAafa8DD400676Df8076AD6c724867b0e2e8', // bDAI 282 | '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI 283 | web3.utils.toWei(inputAmount), 284 | 10, 285 | 4, 286 | ); 287 | 288 | const returnAmount = web3.utils.fromWei(res.returnAmount.toString(), 'ether'); 289 | 290 | assert.strictEqual( 291 | returnAmount, 292 | inputAmount, 293 | 'Invalid swap ratio', 294 | ); 295 | 296 | console.log(`input: ${inputAmount} bDAI`); 297 | console.log(`returnAmount: ${returnAmount} DAI`); 298 | // console.log('distribution:', res.distribution.map(a => a.toString())); 299 | 300 | console.log('raw:', res.returnAmount.toString()); 301 | }); 302 | 303 | it('should give return from ETH to bDAI', async function () { 304 | const inputAmount = '20'; 305 | 306 | const res = await this.split.getExpectedReturn( 307 | '0x0000000000000000000000000000000000000000', // ETH 308 | '0x6a4FFAafa8DD400676Df8076AD6c724867b0e2e8', // bDAI 309 | web3.utils.toWei(inputAmount), 310 | 10, 311 | 4, 312 | ); 313 | 314 | const returnAmount = web3.utils.fromWei(res.returnAmount.toString(), 'ether'); 315 | 316 | console.log(`input: ${inputAmount} ETH`); 317 | console.log(`returnAmount: ${returnAmount} bDAI`); 318 | // console.log('distributionBdai:', res.distribution.map(a => a.toString())); 319 | 320 | console.log('raw:', res.returnAmount.toString()); 321 | }); 322 | }); 323 | }); 324 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | networks: { 5 | development: { 6 | host: 'localhost', 7 | port: 9545, 8 | network_id: '*', 9 | gas: 8000000, 10 | gasPrice: 1000000000, // web3.eth.gasPrice 11 | }, 12 | coverage: { 13 | host: 'localhost', 14 | port: 8555, 15 | network_id: '*', 16 | gas: 8000000, 17 | gasPrice: 1000000000, // web3.eth.gasPrice 18 | } 19 | }, 20 | compilers: { 21 | solc: { 22 | version: '0.5.17', 23 | settings: { 24 | optimizer: { 25 | enabled: true, 26 | runs: 200, 27 | } 28 | } 29 | }, 30 | }, 31 | mocha: { // https://github.com/cgewecke/eth-gas-reporter 32 | reporter: 'eth-gas-reporter', 33 | reporterOptions : { 34 | currency: 'USD', 35 | gasPrice: 10, 36 | onlyCalledMethods: true, 37 | showTimeSpent: true, 38 | excludeContracts: ['Migrations'] 39 | } 40 | } 41 | }; 42 | --------------------------------------------------------------------------------