Address Contract Partially Verified
Address
0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e
Balance
0 ETH
Nonce
1
Code Size
10775 bytes
Creator
0x083fc10c...4E45 at tx 0x65e9d9b8...589905
Indexed Transactions
0 (1 on-chain, 1.2% indexed)
Contract Bytecode
10775 bytes
0x6080604052600436106100e85760003560e01c80638f32d59b1161008a578063c92aecc411610059578063c92aecc4146108f4578063e2a7515e14610909578063e3a5ab78146109d1578063f2fde38b14610b90576100e8565b80638f32d59b146106ae578063b26413f8146106d7578063ba4917b31461070a578063c785139614610743576100e8565b80637b33701a116100c65780637b33701a146102d55780638373f265146105b1578063867807ca146106685780638da5cb5b14610699576100e8565b8063085e2c5b146101295780634080eb7e146101d3578063715018a6146102c0575b333214156101275760405162461bcd60e51b81526004018080602001828103825260228152602001806128496022913960400191505060405180910390fd5b005b34801561013557600080fd5b50610178600480360360a081101561014c57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135610bc3565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156101be5781810151838201526020016101a6565b50505050905001935050505060405180910390f35b6102ae60048036036101008110156101ea57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561022957600080fd5b82018360208201111561023b57600080fd5b803590602001918460208302840111600160201b8311171561025c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101356001600160a01b03169060400135610be6565b60408051918252519081900360200190f35b3480156102cc57600080fd5b50610127610cbc565b3480156102e157600080fd5b50610511600480360360a08110156102f857600080fd5b810190602081018135600160201b81111561031257600080fd5b82018360208201111561032457600080fd5b803590602001918460208302840111600160201b8311171561034557600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092958435959094909350604081019250602001359050600160201b81111561039c57600080fd5b8201836020820111156103ae57600080fd5b803590602001918460208302840111600160201b831117156103cf57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561041e57600080fd5b82018360208201111561043057600080fd5b803590602001918460208302840111600160201b8311171561045157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156104a057600080fd5b8201836020820111156104b257600080fd5b803590602001918460208302840111600160201b831117156104d357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610d4d945050505050565b604051808060200184815260200180602001838103835286818151815260200191508051906020019060200280838360005b8381101561055b578181015183820152602001610543565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561059a578181015183820152602001610582565b505050509050019550505050505060405180910390f35b3480156105bd57600080fd5b50610606600480360360c08110156105d457600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a0013561102c565b6040518084815260200183815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561065257818101518382015260200161063a565b5050505090500194505050505060405180910390f35b34801561067457600080fd5b5061067d611187565b604080516001600160a01b039092168252519081900360200190f35b3480156106a557600080fd5b5061067d611196565b3480156106ba57600080fd5b506106c36111a5565b604080519115158252519081900360200190f35b3480156106e357600080fd5b50610127600480360360208110156106fa57600080fd5b50356001600160a01b03166111c9565b34801561071657600080fd5b506101276004803603604081101561072d57600080fd5b506001600160a01b03813516906020013561125a565b6102ae600480360360a081101561075957600080fd5b810190602081018135600160201b81111561077357600080fd5b82018360208201111561078557600080fd5b803590602001918460208302840111600160201b831117156107a657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295843595602086013595919450925060608101915060400135600160201b81111561080157600080fd5b82018360208201111561081357600080fd5b803590602001918460208302840111600160201b8311171561083457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561088357600080fd5b82018360208201111561089557600080fd5b803590602001918460208302840111600160201b831117156108b657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506112c0945050505050565b34801561090057600080fd5b5061067d6112dc565b6102ae600480360360c081101561091f57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561095e57600080fd5b82018360208201111561097057600080fd5b803590602001918460208302840111600160201b8311171561099157600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506112ee915050565b6102ae600480360360e08110156109e757600080fd5b810190602081018135600160201b811115610a0157600080fd5b820183602082011115610a1357600080fd5b803590602001918460208302840111600160201b83111715610a3457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295843595602086013595919450925060608101915060400135600160201b811115610a8f57600080fd5b820183602082011115610aa157600080fd5b803590602001918460208302840111600160201b83111715610ac257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610b1157600080fd5b820183602082011115610b2357600080fd5b803590602001918460208302840111600160201b83111715610b4457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b03833516935050506020013561130c565b348015610b9c57600080fd5b5061012760048036036020811015610bb357600080fd5b50356001600160a01b03166119f7565b60006060610bd68787878787600061102c565b9199919850909650505050505050565b60408051600280825260608083018452600093909291906020830190803883390190505090508981600081518110610c1a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508881600181518110610c4857fe5b6001600160a01b03909216602092830291909101909101526040805160018082528183019092526060918160200160208202803883390190505090508581600081518110610c9257fe5b602002602001018181525050610cad828a8a8a858a8a61130c565b50505098975050505050505050565b610cc46111a5565b610d03576040805162461bcd60e51b81526020600482018190526024820152600080516020612963833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b606060006060600160009054906101000a90046001600160a01b03166001600160a01b0316637b33701a89898989896040518663ffffffff1660e01b8152600401808060200186815260200180602001806020018060200185810385528a818151815260200191508051906020019060200280838360005b83811015610ddd578181015183820152602001610dc5565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610e1c578181015183820152602001610e04565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610e5b578181015183820152602001610e43565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610e9a578181015183820152602001610e82565b50505050905001995050505050505050505060006040518083038186803b158015610ec457600080fd5b505afa158015610ed8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526060811015610f0157600080fd5b8101908080516040519392919084600160201b821115610f2057600080fd5b908301906020820185811115610f3557600080fd5b82518660208202830111600160201b82111715610f5157600080fd5b82525081516020918201928201910280838360005b83811015610f7e578181015183820152602001610f66565b505050509050016040526020018051906020019092919080516040519392919084600160201b821115610fb057600080fd5b908301906020820185811115610fc557600080fd5b82518660208202830111600160201b82111715610fe157600080fd5b82525081516020918201928201910280838360005b8381101561100e578181015183820152602001610ff6565b50505050905001604052505050925092509250955095509592505050565b60015460408051638373f26560e01b81526001600160a01b038981166004830152888116602483015260448201889052606482018790526084820186905260a4820185905291516000938493606093911691638373f2659160c4808201928792909190829003018186803b1580156110a357600080fd5b505afa1580156110b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260608110156110e057600080fd5b81516020830151604080850180519151939592948301929184600160201b82111561110a57600080fd5b90830190602082018581111561111f57600080fd5b82518660208202830111600160201b8211171561113b57600080fd5b82525081516020918201928201910280838360005b83811015611168578181015183820152602001611150565b5050505090500160405250505092509250925096509650969350505050565b6001546001600160a01b031681565b6000546001600160a01b031690565b600080546001600160a01b03166111ba611a4a565b6001600160a01b031614905090565b6111d16111a5565b611210576040805162461bcd60e51b81526020600482018190526024820152600080516020612963833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f310ba5f1d2ed074b51e2eccd052a47ae9ab7c6b800d1fca3db3999d6a592ca0390600090a250565b6112626111a5565b6112a1576040805162461bcd60e51b81526020600482018190526024820152600080516020612963833981519152604482015290519081900360640190fd5b6112bb6001600160a01b038316338363ffffffff611a4e16565b505050565b60006112d2868686868660008061130c565b5095945050505050565b6d4946c0e9f43f4dee607b0ef1fa1c81565b6000611301878787878787600080610be6565b979650505050505050565b600060028851101580156113205750600087115b611371576040805162461bcd60e51b815260206004820152601d60248201527f4f6e6553706c69743a2073776170206d616b6573206e6f2073656e7365000000604482015290519081900360640190fd5b60018851038451146113b45760405162461bcd60e51b81526004018080602001828103825260278152602001806128e76027913960400191505060405180910390fd5b6113ce6113c089611acc565b6001600160a01b0316611aea565b15153415151461140f5760405162461bcd60e51b815260040180806020018281038252603481526020018061290e6034913960400191505060405180910390fd5b666a94d74f4300008211156114555760405162461bcd60e51b81526004018080602001828103825260218152602001806128c66021913960400191505060405180910390fd5b60005a905061146261282e565b61146d8a6001611b24565b90506114918961147c8c611acc565b6001600160a01b03169063ffffffff611b7016565b60006114c982600001516114bd306114a88f611acc565b6001600160a01b03169063ffffffff611bf216565b9063ffffffff611c9c16565b6001549091506114fc906001600160a01b0316826114e68e611acc565b6001600160a01b0316919063ffffffff611cde16565b6001546001600160a01b031663c78513966115196113c08e611acc565b611524576000611526565b825b8d848d8d8d6040518763ffffffff1660e01b815260040180806020018681526020018581526020018060200180602001848103845289818151815260200191508051906020019060200280838360005b8381101561158e578181015183820152602001611576565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156115cd5781810151838201526020016115b5565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561160c5781810151838201526020016115f4565b50505050905001985050505050505050506020604051808303818588803b15801561163657600080fd5b505af115801561164a573d6000803e3d6000fd5b50505050506040513d602081101561166157600080fd5b5061166c905061282e565b6116778c6000611b24565b905061169483602001518260200151611c9c90919063ffffffff16565b9450898510156116d55760405162461bcd60e51b81526004018080602001828103825260358152602001806128916035913960400191505060405180910390fd5b61172087611701670de0b6b3a76400006116f5898b63ffffffff611dd816565b9063ffffffff611e3116565b61170a8f611e73565b6001600160a01b0316919063ffffffff611a4e16565b5061175133611701611744670de0b6b3a76400006116f58a8c63ffffffff611dd816565b889063ffffffff611c9c16565b5061175b8c611e73565b6001600160a01b031661176d8d611acc565b6001600160a01b03167f97dab93572c2c66c701e75607e2db4045d7b8d0765335338b556929b940707e28d888e8e8e8e8e604051808881526020018781526020018681526020018060200180602001856001600160a01b03166001600160a01b03168152602001848152602001838103835287818151815260200191508051906020019060200280838360005b838110156118125781810151838201526020016117fa565b50505050905001838103825286818151815260200191508051906020019060200280838360005b83811015611851578181015183820152602001611839565b50505050905001995050505050505050505060405180910390a3825181511115611899578251815161189791339161188e9163ffffffff611c9c16565b61170a8f611acc565b505b60006001603e1b6501000000000017896000815181106118b557fe5b6020026020010151161115611915576000601036025a86615208010301905061190f60006001603e1b8b6000815181106118eb57fe5b602002602001015116116118ff5733611901565b325b61a3db61374a840104611e85565b506119e8565b600066800000000000008960008151811061192c57fe5b60200260200101511611156119e8576000601036025a866152080103019050876001600160a01b031663bc3d0d7882886000366040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156119ce57600080fd5b505af11580156119e2573d6000803e3d6000fd5b50505050505b50505050979650505050505050565b6119ff6111a5565b611a3e576040805162461bcd60e51b81526020600482018190526024820152600080516020612963833981519152604482015290519081900360640190fd5b611a47816121ce565b50565b3390565b600081611a5d57506001611ac5565b611a6684611aea565b15611aa7576040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015611aa1573d6000803e3d6000fd5b50611ac5565b611ac16001600160a01b038516848463ffffffff61226e16565b5060015b9392505050565b600081600081518110611adb57fe5b60200260200101519050919050565b60006001600160a01b0382161580611b1e57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b611b2c61282e565b6040518060400160405280611b5584611b46576000611b48565b345b6114bd306114a889611acc565b8152602001611b67306114a887611e73565b90529392505050565b80611b7a57611bee565b611b8382611aea565b15611bd35780341115611bce57336108fc611ba4348463ffffffff611c9c16565b6040518115909202916000818181858888f19350505050158015611bcc573d6000803e3d6000fd5b505b611bee565b611bee6001600160a01b03831633308463ffffffff6122c016565b5050565b6000611bfd83611aea565b15611c1357506001600160a01b03811631611b1e565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611c6957600080fd5b505afa158015611c7d573d6000803e3d6000fd5b505050506040513d6020811015611c9357600080fd5b50519050611b1e565b6000611ac583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061231a565b611ce783611aea565b6112bb5780611d1057611d0b6001600160a01b03841683600063ffffffff6123b116565b6112bb565b60408051636eb1769f60e11b81523060048201526001600160a01b038481166024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d6020811015611d8b57600080fd5b5051905081811015611dd2578015611db857611db86001600160a01b03851684600063ffffffff6123b116565b611dd26001600160a01b038516848463ffffffff6123b116565b50505050565b600082611de757506000611b1e565b82820282848281611df457fe5b0414611ac55760405162461bcd60e51b81526004018080602001828103825260218152602001806129426021913960400191505060405180910390fd5b6000611ac583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506124c4565b600081600183510381518110611adb57fe5b73a6f3ef841d371a82ca757fad08efc0dee2f1f5e26000611eca826d4946c0e9f43f4dee607b0ef1fa1c73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc286612529565b90506000611ef03a611ee48661465063ffffffff611dd816565b9063ffffffff611dd816565b9050611f14611f073a618ca063ffffffff611dd816565b829063ffffffff6125e016565b821015611faa576040805163079d229f60e01b81526001600160a01b03871660048201526024810186905290516d4946c0e9f43f4dee607b0ef1fa1c9163079d229f9160448083019260209291908290030181600087803b158015611f7857600080fd5b505af1158015611f8c573d6000803e3d6000fd5b505050506040513d6020811015611fa257600080fd5b506121c79050565b604080516323b872dd60e01b81526001600160a01b038781166004830152851660248201526044810186905290516d4946c0e9f43f4dee607b0ef1fa1c916323b872dd9160648083019260209291908290030181600087803b15801561200f57600080fd5b505af1158015612023573d6000803e3d6000fd5b505050506040513d602081101561203957600080fd5b50506040805163022c0d9f60e01b815260006004820181905260248201859052306044830152608060648301526084820181905291516001600160a01b0386169263022c0d9f9260c4808201939182900301818387803b15801561209c57600080fd5b505af11580156120b0573d6000803e3d6000fd5b5050604080516370a0823160e01b8152306004820152905173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29350632e1a7d4d925083916370a08231916024808301926020929190829003018186803b15801561210d57600080fd5b505afa158015612121573d6000803e3d6000fd5b505050506040513d602081101561213757600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561217757600080fd5b505af115801561218b573d6000803e3d6000fd5b50506040516001600160a01b03881692504780156108fc029250906000818181858888f193505050501580156121c5573d6000803e3d6000fd5b505b5050505050565b6001600160a01b0381166122135760405162461bcd60e51b815260040180806020018281038252602681526020018061286b6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112bb90849061263a565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611dd290859061263a565b600081848411156123a95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561236e578181015183820152602001612356565b50505050905090810190601f16801561239b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b801580612437575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561240957600080fd5b505afa15801561241d573d6000803e3d6000fd5b505050506040513d602081101561243357600080fd5b5051155b6124725760405162461bcd60e51b81526004018080602001828103825260368152602001806129ad6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526112bb90849061263a565b600081836125135760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561236e578181015183820152602001612356565b50600083858161251f57fe5b0495945050505050565b6000806125456001600160a01b0386168763ffffffff611bf216565b905060006125626001600160a01b0386168863ffffffff611bf216565b90506000612578856103e563ffffffff611dd816565b9050600061258c828463ffffffff611dd816565b905060006125b2836125a6876103e863ffffffff611dd816565b9063ffffffff6125e016565b905080156125cf576125ca828263ffffffff611e3116565b6125d2565b60005b9a9950505050505050505050565b600082820183811015611ac5576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b61264c826001600160a01b03166127f2565b61269d576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106126db5780518252601f1990920191602091820191016126bc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461273d576040519150601f19603f3d011682016040523d82523d6000602084013e612742565b606091505b509150915081612799576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611dd2578080602001905160208110156127b557600080fd5b5051611dd25760405162461bcd60e51b815260040180806020018281038252602a815260200180612983602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061282657508115155b949350505050565b60405180604001604052806000815260200160008152509056fe4f6e6553706c69743a20646f206e6f742073656e6420455448206469726563746c794f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f6e6553706c69743a2061637475616c2072657475726e20616d6f756e74206973206c657373207468616e206d696e52657475726e4f6e6553706c69743a2066656550657263656e74206f7574206f662072616e67654f6e6553706c69743a20666c616773206172726179206c656e67746820697320696e76616c69644f6e6553706c69743a206d73672e76616c75652073686f756c642062652075736564206f6e6c7920666f72204554482073776170536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a265627a7a72315820afdf919e51cffb75aa67ad4bdbc476f3de87671dec116d61aaf65ffe97c1bb3a64736f6c63430005110032
Verified Source Code Partial Match
Compiler: v0.5.17+commit.d19bba13
EVM: istanbul
Optimization: Yes (200 runs)
OneSplitAudit.sol 1209 lines
// File: @openzeppelin/contracts/GSN/Context.sol
pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: @openzeppelin/contracts/ownership/Ownable.sol
pragma solidity ^0.5.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: contracts/interface/IWETH.sol
pragma solidity ^0.5.0;
contract IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
// File: @openzeppelin/contracts/math/SafeMath.sol
pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: @openzeppelin/contracts/utils/Address.sol
pragma solidity ^0.5.5;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-call-value
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol
pragma solidity ^0.5.0;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File: contracts/UniversalERC20.sol
pragma solidity ^0.5.0;
library UniversalERC20 {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 private constant ZERO_ADDRESS = IERC20(0x0000000000000000000000000000000000000000);
IERC20 private constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
function universalTransfer(IERC20 token, address to, uint256 amount) internal returns(bool) {
if (amount == 0) {
return true;
}
if (isETH(token)) {
address(uint160(to)).transfer(amount);
} else {
token.safeTransfer(to, amount);
return true;
}
}
function universalTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {
if (amount == 0) {
return;
}
if (isETH(token)) {
require(from == msg.sender && msg.value >= amount, "Wrong useage of ETH.universalTransferFrom()");
if (to != address(this)) {
address(uint160(to)).transfer(amount);
}
if (msg.value > amount) {
msg.sender.transfer(msg.value.sub(amount));
}
} else {
token.safeTransferFrom(from, to, amount);
}
}
function universalTransferFromSenderToThis(IERC20 token, uint256 amount) internal {
if (amount == 0) {
return;
}
if (isETH(token)) {
if (msg.value > amount) {
// Return remainder if exist
msg.sender.transfer(msg.value.sub(amount));
}
} else {
token.safeTransferFrom(msg.sender, address(this), amount);
}
}
function universalApprove(IERC20 token, address to, uint256 amount) internal {
if (!isETH(token)) {
if (amount == 0) {
token.safeApprove(to, 0);
return;
}
uint256 allowance = token.allowance(address(this), to);
if (allowance < amount) {
if (allowance > 0) {
token.safeApprove(to, 0);
}
token.safeApprove(to, amount);
}
}
}
function universalBalanceOf(IERC20 token, address who) internal view returns (uint256) {
if (isETH(token)) {
return who.balance;
} else {
return token.balanceOf(who);
}
}
function universalDecimals(IERC20 token) internal view returns (uint256) {
if (isETH(token)) {
return 18;
}
(bool success, bytes memory data) = address(token).staticcall.gas(10000)(
abi.encodeWithSignature("decimals()")
);
if (!success || data.length == 0) {
(success, data) = address(token).staticcall.gas(10000)(
abi.encodeWithSignature("DECIMALS()")
);
}
return (success && data.length > 0) ? abi.decode(data, (uint256)) : 18;
}
function isETH(IERC20 token) internal pure returns(bool) {
return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS));
}
function notExist(IERC20 token) internal pure returns(bool) {
return (address(token) == address(-1));
}
}
// File: contracts/interface/IUniswapV2Exchange.sol
pragma solidity ^0.5.0;
interface IUniswapV2Exchange {
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}
library UniswapV2ExchangeLib {
using SafeMath for uint256;
using UniversalERC20 for IERC20;
function getReturn(
IUniswapV2Exchange exchange,
IERC20 fromToken,
IERC20 destToken,
uint amountIn
) internal view returns (uint256) {
uint256 reserveIn = fromToken.universalBalanceOf(address(exchange));
uint256 reserveOut = destToken.universalBalanceOf(address(exchange));
uint256 amountInWithFee = amountIn.mul(997);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
return (denominator == 0) ? 0 : numerator.div(denominator);
}
}
// File: contracts/IOneSplit.sol
pragma solidity ^0.5.0;
//
// [ msg.sender ]
// | |
// | |
// \_/
// +---------------+ ________________________________
// | OneSplitAudit | _______________________________ \
// +---------------+ \ \
// | | ______________ | | (staticcall)
// | | / ____________ \ | |
// | | (call) / / \ \ | |
// | | / / | | | |
// \_/ | | \_/ \_/
// +--------------+ | | +----------------------+
// | OneSplitWrap | | | | OneSplitViewWrap |
// +--------------+ | | +----------------------+
// | | | | | |
// | | (delegatecall) | | (staticcall) | | (staticcall)
// \_/ | | \_/
// +--------------+ | | +------------------+
// | OneSplit | | | | OneSplitView |
// +--------------+ | | +------------------+
// | | / /
// \ \________________/ /
// \__________________/
//
contract IOneSplitConsts {
// flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_BANCOR + ...
uint256 internal constant FLAG_DISABLE_UNISWAP = 0x01;
uint256 internal constant DEPRECATED_FLAG_DISABLE_KYBER = 0x02; // Deprecated
uint256 internal constant FLAG_DISABLE_BANCOR = 0x04;
uint256 internal constant FLAG_DISABLE_OASIS = 0x08;
uint256 internal constant FLAG_DISABLE_COMPOUND = 0x10;
uint256 internal constant FLAG_DISABLE_FULCRUM = 0x20;
uint256 internal constant FLAG_DISABLE_CHAI = 0x40;
uint256 internal constant FLAG_DISABLE_AAVE = 0x80;
uint256 internal constant FLAG_DISABLE_SMART_TOKEN = 0x100;
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_ETH = 0x200; // Deprecated, Turned off by default
uint256 internal constant FLAG_DISABLE_BDAI = 0x400;
uint256 internal constant FLAG_DISABLE_IEARN = 0x800;
uint256 internal constant FLAG_DISABLE_CURVE_COMPOUND = 0x1000;
uint256 internal constant FLAG_DISABLE_CURVE_USDT = 0x2000;
uint256 internal constant FLAG_DISABLE_CURVE_Y = 0x4000;
uint256 internal constant FLAG_DISABLE_CURVE_BINANCE = 0x8000;
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_DAI = 0x10000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_USDC = 0x20000; // Deprecated, Turned off by default
uint256 internal constant FLAG_DISABLE_CURVE_SYNTHETIX = 0x40000;
uint256 internal constant FLAG_DISABLE_WETH = 0x80000;
uint256 internal constant FLAG_DISABLE_UNISWAP_COMPOUND = 0x100000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH
uint256 internal constant FLAG_DISABLE_UNISWAP_CHAI = 0x200000; // Works only when ETH<>DAI or FLAG_ENABLE_MULTI_PATH_ETH
uint256 internal constant FLAG_DISABLE_UNISWAP_AAVE = 0x400000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH
uint256 internal constant FLAG_DISABLE_IDLE = 0x800000;
uint256 internal constant FLAG_DISABLE_MOONISWAP = 0x1000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_V2 = 0x2000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_V2_ETH = 0x4000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_V2_DAI = 0x8000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_V2_USDC = 0x10000000;
uint256 internal constant FLAG_DISABLE_ALL_SPLIT_SOURCES = 0x20000000;
uint256 internal constant FLAG_DISABLE_ALL_WRAP_SOURCES = 0x40000000;
uint256 internal constant FLAG_DISABLE_CURVE_PAX = 0x80000000;
uint256 internal constant FLAG_DISABLE_CURVE_RENBTC = 0x100000000;
uint256 internal constant FLAG_DISABLE_CURVE_TBTC = 0x200000000;
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_USDT = 0x400000000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_WBTC = 0x800000000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_TBTC = 0x1000000000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_RENBTC = 0x2000000000; // Deprecated, Turned off by default
uint256 internal constant FLAG_DISABLE_DFORCE_SWAP = 0x4000000000;
uint256 internal constant FLAG_DISABLE_SHELL = 0x8000000000;
uint256 internal constant FLAG_ENABLE_CHI_BURN = 0x10000000000;
uint256 internal constant FLAG_DISABLE_MSTABLE_MUSD = 0x20000000000;
uint256 internal constant FLAG_DISABLE_CURVE_SBTC = 0x40000000000;
uint256 internal constant FLAG_DISABLE_DMM = 0x80000000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_ALL = 0x100000000000;
uint256 internal constant FLAG_DISABLE_CURVE_ALL = 0x200000000000;
uint256 internal constant FLAG_DISABLE_UNISWAP_V2_ALL = 0x400000000000;
uint256 internal constant FLAG_DISABLE_SPLIT_RECALCULATION = 0x800000000000;
uint256 internal constant FLAG_DISABLE_BALANCER_ALL = 0x1000000000000;
uint256 internal constant FLAG_DISABLE_BALANCER_1 = 0x2000000000000;
uint256 internal constant FLAG_DISABLE_BALANCER_2 = 0x4000000000000;
uint256 internal constant FLAG_DISABLE_BALANCER_3 = 0x8000000000000;
uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_UNISWAP_RESERVE = 0x10000000000000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_OASIS_RESERVE = 0x20000000000000; // Deprecated, Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_KYBER_BANCOR_RESERVE = 0x40000000000000; // Deprecated, Turned off by default
uint256 internal constant FLAG_ENABLE_REFERRAL_GAS_SPONSORSHIP = 0x80000000000000; // Turned off by default
uint256 internal constant DEPRECATED_FLAG_ENABLE_MULTI_PATH_COMP = 0x100000000000000; // Deprecated, Turned off by default
uint256 internal constant FLAG_DISABLE_KYBER_ALL = 0x200000000000000;
uint256 internal constant FLAG_DISABLE_KYBER_1 = 0x400000000000000;
uint256 internal constant FLAG_DISABLE_KYBER_2 = 0x800000000000000;
uint256 internal constant FLAG_DISABLE_KYBER_3 = 0x1000000000000000;
uint256 internal constant FLAG_DISABLE_KYBER_4 = 0x2000000000000000;
uint256 internal constant FLAG_ENABLE_CHI_BURN_BY_ORIGIN = 0x4000000000000000;
}
contract IOneSplit is IOneSplitConsts {
function getExpectedReturn(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 parts,
uint256 flags // See constants in IOneSplit.sol
)
public
view
returns(
uint256 returnAmount,
uint256[] memory distribution
);
function getExpectedReturnWithGas(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 parts,
uint256 flags, // See constants in IOneSplit.sol
uint256 destTokenEthPriceTimesGasPrice
)
public
view
returns(
uint256 returnAmount,
uint256 estimateGasAmount,
uint256[] memory distribution
);
function swap(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256 flags
)
public
payable
returns(uint256 returnAmount);
}
contract IOneSplitMulti is IOneSplit {
function getExpectedReturnWithGasMulti(
IERC20[] memory tokens,
uint256 amount,
uint256[] memory parts,
uint256[] memory flags,
uint256[] memory destTokenEthPriceTimesGasPrices
)
public
view
returns(
uint256[] memory returnAmounts,
uint256 estimateGasAmount,
uint256[] memory distribution
);
function swapMulti(
IERC20[] memory tokens,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256[] memory flags
)
public
payable
returns(uint256 returnAmount);
}
// File: contracts/OneSplitAudit.sol
pragma solidity ^0.5.0;
contract IFreeFromUpTo is IERC20 {
function freeFromUpTo(address from, uint256 value) external returns(uint256 freed);
}
interface IReferralGasSponsor {
function makeGasDiscount(
uint256 gasSpent,
uint256 returnAmount,
bytes calldata msgSenderCalldata
) external;
}
library Array {
function first(IERC20[] memory arr) internal pure returns(IERC20) {
return arr[0];
}
function last(IERC20[] memory arr) internal pure returns(IERC20) {
return arr[arr.length - 1];
}
}
//
// Security assumptions:
// 1. It is safe to have infinite approves of any tokens to this smart contract,
// since it could only call `transferFrom()` with first argument equal to msg.sender
// 2. It is safe to call `swap()` with reliable `minReturn` argument,
// if returning amount will not reach `minReturn` value whole swap will be reverted.
// 3. Additionally CHI tokens could be burned from caller in case of FLAG_ENABLE_CHI_BURN (0x10000000000)
// presented in `flags` or from transaction origin in case of FLAG_ENABLE_CHI_BURN_BY_ORIGIN (0x4000000000000000)
// presented in `flags`. Burned amount would refund up to 43% of gas fees.
//
contract OneSplitAudit is IOneSplit, Ownable {
using SafeMath for uint256;
using UniversalERC20 for IERC20;
using Array for IERC20[];
IWETH constant internal weth = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IFreeFromUpTo public constant chi = IFreeFromUpTo(0x0000000000004946c0e9F43F4Dee607b0eF1fA1c);
IOneSplitMulti public oneSplitImpl;
event ImplementationUpdated(address indexed newImpl);
event Swapped(
IERC20 indexed fromToken,
IERC20 indexed destToken,
uint256 fromTokenAmount,
uint256 destTokenAmount,
uint256 minReturn,
uint256[] distribution,
uint256[] flags,
address referral,
uint256 feePercent
);
constructor(IOneSplitMulti impl) public {
setNewImpl(impl);
}
function() external payable {
// solium-disable-next-line security/no-tx-origin
require(msg.sender != tx.origin, "OneSplit: do not send ETH directly");
}
function setNewImpl(IOneSplitMulti impl) public onlyOwner {
oneSplitImpl = impl;
emit ImplementationUpdated(address(impl));
}
/// @notice Calculate expected returning amount of `destToken`
/// @param fromToken (IERC20) Address of token or `address(0)` for Ether
/// @param destToken (IERC20) Address of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param parts (uint256) Number of pieces source volume could be splitted,
/// works like granularity, higly affects gas usage. Should be called offchain,
/// but could be called onchain if user swaps not his own funds, but this is still considered as not safe.
/// @param flags (uint256) Flags for enabling and disabling some features, default 0
function getExpectedReturn(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 parts,
uint256 flags // See contants in IOneSplit.sol
)
public
view
returns(
uint256 returnAmount,
uint256[] memory distribution
)
{
(returnAmount, , distribution) = getExpectedReturnWithGas(
fromToken,
destToken,
amount,
parts,
flags,
0
);
}
/// @notice Calculate expected returning amount of `destToken`
/// @param fromToken (IERC20) Address of token or `address(0)` for Ether
/// @param destToken (IERC20) Address of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param parts (uint256) Number of pieces source volume could be splitted,
/// works like granularity, higly affects gas usage. Should be called offchain,
/// but could be called onchain if user swaps not his own funds, but this is still considered as not safe.
/// @param flags (uint256) Flags for enabling and disabling some features, default 0
/// @param destTokenEthPriceTimesGasPrice (uint256) destToken price to ETH multiplied by gas price
function getExpectedReturnWithGas(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 parts,
uint256 flags, // See constants in IOneSplit.sol
uint256 destTokenEthPriceTimesGasPrice
)
public
view
returns(
uint256 returnAmount,
uint256 estimateGasAmount,
uint256[] memory distribution
)
{
return oneSplitImpl.getExpectedReturnWithGas(
fromToken,
destToken,
amount,
parts,
flags,
destTokenEthPriceTimesGasPrice
);
}
/// @notice Calculate expected returning amount of first `tokens` element to
/// last `tokens` element through ann the middle tokens with corresponding
/// `parts`, `flags` and `destTokenEthPriceTimesGasPrices` array values of each step
/// @param tokens (IERC20[]) Address of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param parts (uint256[]) Number of pieces source volume could be splitted
/// @param flags (uint256[]) Flags for enabling and disabling some features, default 0
/// @param destTokenEthPriceTimesGasPrices (uint256[]) destToken price to ETH multiplied by gas price
function getExpectedReturnWithGasMulti(
IERC20[] memory tokens,
uint256 amount,
uint256[] memory parts,
uint256[] memory flags,
uint256[] memory destTokenEthPriceTimesGasPrices
)
public
view
returns(
uint256[] memory returnAmounts,
uint256 estimateGasAmount,
uint256[] memory distribution
)
{
return oneSplitImpl.getExpectedReturnWithGasMulti(
tokens,
amount,
parts,
flags,
destTokenEthPriceTimesGasPrices
);
}
/// @notice Swap `amount` of `fromToken` to `destToken`
/// @param fromToken (IERC20) Address of token or `address(0)` for Ether
/// @param destToken (IERC20) Address of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param minReturn (uint256) Minimum expected return, else revert
/// @param distribution (uint256[]) Array of weights for volume distribution returned by `getExpectedReturn`
/// @param flags (uint256) Flags for enabling and disabling some features, default 0
function swap(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256 flags // See contants in IOneSplit.sol
) public payable returns(uint256) {
return swapWithReferral(
fromToken,
destToken,
amount,
minReturn,
distribution,
flags,
address(0),
0
);
}
/// @notice Swap `amount` of `fromToken` to `destToken`
/// param fromToken (IERC20) Address of token or `address(0)` for Ether
/// param destToken (IERC20) Address of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param minReturn (uint256) Minimum expected return, else revert
/// @param distribution (uint256[]) Array of weights for volume distribution returned by `getExpectedReturn`
/// @param flags (uint256) Flags for enabling and disabling some features, default 0
/// @param referral (address) Address of referral
/// @param feePercent (uint256) Fees percents normalized to 1e18, limited to 0.03e18 (3%)
function swapWithReferral(
IERC20 fromToken,
IERC20 destToken,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256 flags, // See contants in IOneSplit.sol
address referral,
uint256 feePercent
) public payable returns(uint256) {
IERC20[] memory tokens = new IERC20[](2);
tokens[0] = fromToken;
tokens[1] = destToken;
uint256[] memory flagsArray = new uint256[](1);
flagsArray[0] = flags;
swapWithReferralMulti(
tokens,
amount,
minReturn,
distribution,
flagsArray,
referral,
feePercent
);
}
/// @notice Swap `amount` of first element of `tokens` to the latest element of `destToken`
/// @param tokens (IERC20[]) Addresses of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param minReturn (uint256) Minimum expected return, else revert
/// @param distribution (uint256[]) Array of weights for volume distribution returned by `getExpectedReturn`
/// @param flags (uint256[]) Flags for enabling and disabling some features, default 0
function swapMulti(
IERC20[] memory tokens,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256[] memory flags
) public payable returns(uint256) {
swapWithReferralMulti(
tokens,
amount,
minReturn,
distribution,
flags,
address(0),
0
);
}
/// @notice Swap `amount` of first element of `tokens` to the latest element of `destToken`
/// @param tokens (IERC20[]) Addresses of token or `address(0)` for Ether
/// @param amount (uint256) Amount for `fromToken`
/// @param minReturn (uint256) Minimum expected return, else revert
/// @param distribution (uint256[]) Array of weights for volume distribution returned by `getExpectedReturn`
/// @param flags (uint256[]) Flags for enabling and disabling some features, default 0
/// @param referral (address) Address of referral
/// @param feePercent (uint256) Fees percents normalized to 1e18, limited to 0.03e18 (3%)
function swapWithReferralMulti(
IERC20[] memory tokens,
uint256 amount,
uint256 minReturn,
uint256[] memory distribution,
uint256[] memory flags,
address referral,
uint256 feePercent
) public payable returns(uint256 returnAmount) {
require(tokens.length >= 2 && amount > 0, "OneSplit: swap makes no sense");
require(flags.length == tokens.length - 1, "OneSplit: flags array length is invalid");
require((msg.value != 0) == tokens.first().isETH(), "OneSplit: msg.value should be used only for ETH swap");
require(feePercent <= 0.03e18, "OneSplit: feePercent out of range");
uint256 gasStart = gasleft();
Balances memory beforeBalances = _getFirstAndLastBalances(tokens, true);
// Transfer From
tokens.first().universalTransferFromSenderToThis(amount);
uint256 confirmed = tokens.first().universalBalanceOf(address(this)).sub(beforeBalances.ofFromToken);
// Swap
tokens.first().universalApprove(address(oneSplitImpl), confirmed);
oneSplitImpl.swapMulti.value(tokens.first().isETH() ? confirmed : 0)(
tokens,
confirmed,
minReturn,
distribution,
flags
);
Balances memory afterBalances = _getFirstAndLastBalances(tokens, false);
// Return
returnAmount = afterBalances.ofDestToken.sub(beforeBalances.ofDestToken);
require(returnAmount >= minReturn, "OneSplit: actual return amount is less than minReturn");
tokens.last().universalTransfer(referral, returnAmount.mul(feePercent).div(1e18));
tokens.last().universalTransfer(msg.sender, returnAmount.sub(returnAmount.mul(feePercent).div(1e18)));
emit Swapped(
tokens.first(),
tokens.last(),
amount,
returnAmount,
minReturn,
distribution,
flags,
referral,
feePercent
);
// Return remainder
if (afterBalances.ofFromToken > beforeBalances.ofFromToken) {
tokens.first().universalTransfer(msg.sender, afterBalances.ofFromToken.sub(beforeBalances.ofFromToken));
}
if ((flags[0] & (FLAG_ENABLE_CHI_BURN | FLAG_ENABLE_CHI_BURN_BY_ORIGIN)) > 0) {
uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length;
_chiBurnOrSell(
((flags[0] & FLAG_ENABLE_CHI_BURN_BY_ORIGIN) > 0) ? tx.origin : msg.sender,
(gasSpent + 14154) / 41947
);
}
else if ((flags[0] & FLAG_ENABLE_REFERRAL_GAS_SPONSORSHIP) > 0) {
uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length;
IReferralGasSponsor(referral).makeGasDiscount(gasSpent, returnAmount, msg.data);
}
}
function claimAsset(IERC20 asset, uint256 amount) public onlyOwner {
asset.universalTransfer(msg.sender, amount);
}
function _chiBurnOrSell(address payable sponsor, uint256 amount) internal {
IUniswapV2Exchange exchange = IUniswapV2Exchange(0xa6f3ef841d371a82ca757FaD08efc0DeE2F1f5e2);
uint256 sellRefund = UniswapV2ExchangeLib.getReturn(exchange, chi, weth, amount);
uint256 burnRefund = amount.mul(18_000).mul(tx.gasprice);
if (sellRefund < burnRefund.add(tx.gasprice.mul(36_000))) {
chi.freeFromUpTo(sponsor, amount);
}
else {
chi.transferFrom(sponsor, address(exchange), amount);
exchange.swap(0, sellRefund, address(this), "");
weth.withdraw(weth.balanceOf(address(this)));
sponsor.transfer(address(this).balance);
}
}
struct Balances {
uint256 ofFromToken;
uint256 ofDestToken;
}
function _getFirstAndLastBalances(IERC20[] memory tokens, bool subValue) internal view returns(Balances memory) {
return Balances({
ofFromToken: tokens.first().universalBalanceOf(address(this)).sub(subValue ? msg.value : 0),
ofDestToken: tokens.last().universalBalanceOf(address(this))
});
}
}
Read Contract
chi 0xc92aecc4 → address
getExpectedReturn 0x085e2c5b → uint256, uint256[]
getExpectedReturnWithGas 0x8373f265 → uint256, uint256, uint256[]
getExpectedReturnWithGasMulti 0x7b33701a → uint256[], uint256, uint256[]
isOwner 0x8f32d59b → bool
oneSplitImpl 0x867807ca → address
owner 0x8da5cb5b → address
Write Contract 8 functions
These functions modify contract state and require a wallet transaction to execute.
claimAsset 0xba4917b3
address asset
uint256 amount
renounceOwnership 0x715018a6
No parameters
setNewImpl 0xb26413f8
address impl
swap 0xe2a7515e
address fromToken
address destToken
uint256 amount
uint256 minReturn
uint256[] distribution
uint256 flags
returns: uint256
swapMulti 0xc7851396
address[] tokens
uint256 amount
uint256 minReturn
uint256[] distribution
uint256[] flags
returns: uint256
swapWithReferral 0x4080eb7e
address fromToken
address destToken
uint256 amount
uint256 minReturn
uint256[] distribution
uint256 flags
address referral
uint256 feePercent
returns: uint256
swapWithReferralMulti 0xe3a5ab78
address[] tokens
uint256 amount
uint256 minReturn
uint256[] distribution
uint256[] flags
address referral
uint256 feePercent
returns: uint256
transferOwnership 0xf2fde38b
address newOwner
Recent Transactions
This address has 1 on-chain transactions, but only 1.2% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →