Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x4BCafe6C4147E640eD467290cEB6F658187a6E91
Balance 0.027906 ETH
Nonce 1
Code Size 9640 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9640 bytes
0x6080604052600436106100f35760003560e01c806397cf5e851161008a578063cb85ce6711610059578063cb85ce6714610424578063d7628cb914610455578063da09c72c14610488578063ec9790821461049d576100f3565b806397cf5e85146102e2578063a0eefff014610339578063c1ec95c01461037d578063c717978f146103ea576100f3565b806333763d9a116100c657806333763d9a1461021557806342edd8e01461023f5780635bdc609b1461027257806379c7ba5d146102ae576100f3565b8063042bbe3a146100f85780630fe31eb1146101265780631b54cc881461015f578063232b956c146101ac575b600080fd5b6101246004803603604081101561010e57600080fd5b506001600160a01b0381351690602001356104b2565b005b34801561013257600080fd5b506101246004803603604081101561014957600080fd5b506001600160a01b0381351690602001356105d8565b34801561016b57600080fd5b5061019a6004803603604081101561018257600080fd5b506001600160a01b03813581169160200135166106d6565b60408051918252519081900360200190f35b3480156101b857600080fd5b506101d6600480360360208110156101cf57600080fd5b50356106f3565b604080516001600160a01b0390951685526001600160601b039384166020860152919092168382015261ffff9091166060830152519081900360800190f35b34801561022157600080fd5b5061019a6004803603602081101561023857600080fd5b5035610749565b34801561024b57600080fd5b506101246004803603602081101561026257600080fd5b50356001600160a01b031661075b565b6101246004803603608081101561028857600080fd5b5080359063ffffffff6020820135169062ffffff60408201358116916060013516610808565b3480156102ba57600080fd5b50610124600480360360408110156102d157600080fd5b508035906020013561ffff16610c7c565b3480156102ee57600080fd5b506101246004803603608081101561030557600080fd5b5080356001600160a01b03169060208101356001600160601b03908116916040810135909116906060013561ffff16610d13565b610124600480360360a081101561034f57600080fd5b5080359063ffffffff6020820135169062ffffff604082013581169160608101359091169060800135610ee0565b34801561038957600080fd5b506103ad600480360360408110156103a057600080fd5b5080359060200135611331565b6040805163ffffffff909516855262ffffff938416602086015291909216838201526001600160a01b039091166060830152519081900360800190f35b6101246004803603608081101561040057600080fd5b5080359063ffffffff6020820135169062ffffff604082013516906060013561138b565b34801561043057600080fd5b506104396119d5565b604080516001600160a01b039092168252519081900360200190f35b34801561046157600080fd5b506101246004803603602081101561047857600080fd5b50356001600160a01b03166119e4565b34801561049457600080fd5b50610439611a91565b3480156104a957600080fd5b5061019a611aa0565b336001600160a01b03831661051c576001600160a01b038082166000908152600260209081526040808320938716835292905220546104f19034611aa6565b6001600160a01b03808316600090815260026020908152604080832093881683529290522055610588565b6105316001600160a01b038416823085611aef565b6001600160a01b038082166000908152600260209081526040808320938716835292905220546105619083611aa6565b6001600160a01b038083166000908152600260209081526040808320938816835292905220555b826001600160a01b0316816001600160a01b03167f58aaa25e49f6db631eebde1d004a0f3cb1cae2cb4008f61d5e6a7081e0e2ea0a846040518082815260200191505060405180910390a3505050565b3360008181526002602090815260408083206001600160a01b03871684529091529020546106069083611b4f565b6001600160a01b03808316600090815260026020908152604080832093881680845293909152902091909155610672576040516001600160a01b0382169083156108fc029084906000818181858888f1935050505015801561066c573d6000803e3d6000fd5b50610686565b6106866001600160a01b0384168284611b94565b826001600160a01b0316816001600160a01b03167f0586cc6cb62e10f10d84ac63e536d8276b8ab868d370ff7744566a4137316fc3846040518082815260200191505060405180910390a3505050565b600260209081526000928352604080842090915290825290205481565b6003818154811061070057fe5b6000918252602090912060029091020180546001909101546001600160a01b03821692506001600160601b03600160a01b90920482169181169061ffff600160601b9091041684565b60009081526004602052604090205490565b6000546001600160a01b031633146107a3576040805162461bcd60e51b8152602060048083019190915260248201526310b3b7bb60e11b604482015290519081900360640190fd5b6001600160a01b0381166107e6576040805162461bcd60e51b815260206004820152600560248201526410b0b2323960d91b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60008262ffffff161161084e576040805162461bcd60e51b81526020600482015260096024820152682170726963654c6f7760b81b604482015290519081900360640190fd5b60008162ffffff1611610895576040805162461bcd60e51b815260206004820152600a602482015269042e0e4d2c6ca90d2ced60b31b604482015290519081900360640190fd5b8162ffffff168162ffffff1610156108e2576040805162461bcd60e51b815260206004820152600b60248201526a21707269636552616e676560a81b604482015290519081900360640190fd5b600184166108ee612521565b600360028704815481106108fe57fe5b600091825260209182902060408051608081018252600290930290910180546001600160a01b0381168085526001600160601b03600160a01b9092048216958501959095526001909101549081169183019190915261ffff600160601b90910416606082015291506109a1576040805162461bcd60e51b8152602060048201526007602482015266085b585c9ad95d60ca1b604482015290519081900360640190fd5b338215610a2c57600082604001516002026001600160601b03168562ffffff168762ffffff160184602001516001600160601b03168963ffffffff160202816109e657fe5b049050803414610a26576040805162461bcd60e51b81526020600480830191909152602482015263042cae8d60e31b604482015290519081900360640190fd5b50610aad565b815163ffffffff871615610a6f57610a6f823085602001516001600160601b03168a63ffffffff1602846001600160a01b0316611aef909392919063ffffffff16565b3415610aab576040805162461bcd60e51b81526020600480830191909152602482015263042cae8d60e31b604482015290519081900360640190fd5b505b610ab5612521565b8181606001906001600160a01b031690816001600160a01b03168152505086816000019063ffffffff16908163ffffffff168152505085816020019062ffffff16908162ffffff168152505084816040019062ffffff16908162ffffff16815250506000600460008a8152602001908152602001600020905080829080600181540180825580915050600190039060005260206000200160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548162ffffff021916908362ffffff16021790555060408201518160000160076101000a81548162ffffff021916908362ffffff160217905550606082015181600001600a6101000a8154816001600160a01b0302191690836001600160a01b031602179055505050600060018280549050039050600060388862ffffff16901b62ffffff1660208a62ffffff16901b62ffffff168b171763ffffffff169050818b866001600160a01b03167f219ffa51265844bd01d3b42f033eed7742d9447a7237f1b733f3dbcae03dfe72846040518082815260200191505060405180910390a45050505050505050505050565b6000546001600160a01b03163314610cc4576040805162461bcd60e51b8152602060048083019190915260248201526310b3b7bb60e11b604482015290519081900360640190fd5b603c8161ffff161115610cd657600080fd5b8060038381548110610ce457fe5b9060005260206000209060020201600101600c6101000a81548161ffff021916908361ffff1602179055505050565b6000546001600160a01b03163314610d5b576040805162461bcd60e51b8152602060048083019190915260248201526310b3b7bb60e11b604482015290519081900360640190fd5b6000836001600160601b031611610d7157600080fd5b6000826001600160601b031611610d8757600080fd5b603c8161ffff161115610d9957600080fd5b610da1612521565b6001600160a01b038086168083526001600160601b038087166020808601828152888416604080890182815261ffff808c1660608c019081526003805460018101825560008290528d5160029091027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b8101805499518d16600160a01b02928f166001600160a01b0319909a1699909917909d161790965591517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c909a0180549251909116600160601b0261ffff60601b199a9098166bffffffffffffffffffffffff1990921691909117989098169590951790965554835192835290820194909452815160001994909401937f6519feb3e6be8989ebf94368dcc591b9635818a96e48eb37719b4c364b69c214929181900390910190a35050505050565b60008362ffffff1611610f26576040805162461bcd60e51b81526020600482015260096024820152682170726963654c6f7760b81b604482015290519081900360640190fd5b60008262ffffff1611610f6d576040805162461bcd60e51b815260206004820152600a602482015269042e0e4d2c6ca90d2ced60b31b604482015290519081900360640190fd5b8262ffffff168262ffffff161015610fba576040805162461bcd60e51b815260206004820152600b60248201526a21707269636552616e676560a81b604482015290519081900360640190fd5b600085815260046020526040812080543392919084908110610fd857fe5b600091825260209091200180549091506001600160a01b03838116600160501b9092041614611036576040805162461bcd60e51b815260206004820152600560248201526410bab9b2b960d91b604482015290519081900360640190fd5b60018716611042612521565b600360028a048154811061105257fe5b60009182526020918290206040805160808101825260029390930290910180546001600160a01b0381168452600160a01b90046001600160601b03908116948401949094526001015492831690820152600160601b90910461ffff166060820152905081156111ab576040810151835460208301516000926001600160601b03600290910281169263ffffffff81169190921602600160201b820462ffffff908116600160381b9093041691909101028161110957fe5b049050600082604001516002026001600160601b03168862ffffff168a62ffffff160184602001516001600160601b03168c63ffffffff1602028161114a57fe5b04905060006111638261115d3486611aa6565b90611b4f565b905080156111a3576040516001600160a01b0388169082156108fc029083906000818181858888f193505050501580156111a1573d6000803e3d6000fd5b505b505050611251565b6020810151835482516001600160601b0390921663ffffffff918216810292918b160290828211156111f3576111ee6001600160a01b0382168830868603611aef565b611211565b82821015611211576112116001600160a01b03821688848603611b94565b341561124d576040805162461bcd60e51b81526020600480830191909152602482015263042cae8d60e31b604482015290519081900360640190fd5b5050505b825463ffffffff89811691161461127657825463ffffffff191663ffffffff89161783555b825462ffffff888116600160201b90920416146112a957825466ffffff000000001916600160201b62ffffff8916021783555b825462ffffff878116600160381b90920416146112db57825462ffffff60381b1916600160381b62ffffff8816021783555b6040805163ffffffff8a16808252915187918c916001600160a01b038916917fbfae90e027bbda5ea36db1fb40d3f291424a5336695de8b99136e7093e45d3f3919081900360200190a450505050505050505050565b6004602052816000526040600020818154811061134a57fe5b60009182526020909120015463ffffffff8116925062ffffff600160201b820481169250600160381b820416906001600160a01b03600160501b9091041684565b60008481526004602052604081208054839081106113a557fe5b90600052602060002001905060008463ffffffff16116113f5576040805162461bcd60e51b8152602060048083019190915260248201526308585b5d60e21b604482015290519081900360640190fd5b805463ffffffff16611437576040805162461bcd60e51b8152602060048083019190915260248201526308585b5d60e21b604482015290519081900360640190fd5b80543390600160501b90046001600160a01b031660018716611457612521565b600360028a048154811061146757fe5b6000918252602080832060408051608081018252600290940290910180546001600160a01b0381168086526001600160601b03600160a01b9092048216948601949094526001909101549081169184019190915261ffff600160601b909104166060830152875491935091908190600160201b810462ffffff908116600160381b90920416141561160e578754600160201b900462ffffff16851561154e578a62ffffff16811015611549576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b611591565b8a62ffffff16811115611591576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b885463ffffffff808e169450168311156115b057885463ffffffff1692505b84604001516001600160601b03168186602001516001600160601b0316850202816115d757fe5b8a5491900492506115f39063ffffffff908116908590611b4f16565b895463ffffffff191663ffffffff9190911617895550611677565b875462ffffff600160201b82048116600160381b9092041611611664576040805162461bcd60e51b815260206004820152600960248201526810b130b227b93232b960b91b604482015290519081900360640190fd5b6116718885878e8e611beb565b90925090505b600082116116c2576040805162461bcd60e51b815260206004820152601360248201527208599a5b1b151bdad95b905b5d14d8d85b1959606a1b604482015290519081900360640190fd5b60008111611705576040805162461bcd60e51b815260206004820152600b60248201526a08599a5b1b115d1a105b5d60aa1b604482015290519081900360640190fd5b60208401516001600160601b031682028515611821576117306001600160a01b038516898984611aef565b6000612710866060015161ffff1684028161174757fe5b6001546001600160a01b03166000908152600260209081526040808320838052909152902054919004915061177c9082611aa6565b6001546001600160a01b03908116600090815260026020908152604080832083805290915290209190915589166108fc6117b68584611b4f565b6040518115909202916000818181858888f193505050501580156117de573d6000803e3d6000fd5b50341561181b576040805162461bcd60e51b81526020600480830191909152602482015263042cae8d60e31b604482015290519081900360640190fd5b50611966565b8134101561185f576040805162461bcd60e51b81526020600480830191909152602482015263042cae8d60e31b604482015290519081900360640190fd5b6118736001600160a01b0385168983611b94565b6000612710866060015161ffff1684028161188a57fe5b6001546001600160a01b0316600090815260026020908152604080832083805290915290205491900491506118bf9082611aa6565b6001546001600160a01b03908116600090815260026020908152604080832083805290915290209190915588166108fc6118f98584611b4f565b6040518115909202916000818181858888f19350505050158015611921573d6000803e3d6000fd5b5082341115611964576040516001600160a01b038a16903485900380156108fc02916000818181858888f19350505050158015611962573d6000803e3d6000fd5b505b505b6000602083901b841790508a8e8a6001600160a01b03167f05e0db78ec0e4b398d129053215be9d7cdf64d7fa53c1c1b6c2bc780dc73bc7b8b8560405180836001600160a01b031681526020018281526020019250505060405180910390a45050505050505050505050505050565b6000546001600160a01b031681565b6000546001600160a01b03163314611a2c576040805162461bcd60e51b8152602060048083019190915260248201526310b3b7bb60e11b604482015290519081900360640190fd5b6001600160a01b038116611a6f576040805162461bcd60e51b815260206004820152600560248201526410b0b2323960d91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b60035490565b600082820183811015611ae8576040805162461bcd60e51b8152602060048201526005602482015264084858591960da1b604482015290519081900360640190fd5b9392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b4990859061232d565b50505050565b600082821115611b8e576040805162461bcd60e51b81526020600482015260056024820152641090b9bab160d91b604482015290519081900360640190fd5b50900390565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611be690849061232d565b505050565b8454600090819062ffffff600160201b82048116600160381b83049091160360010190829063ffffffff908116908716830281611c2457fe5b04905081811115611c325750805b861561204257885462ffffff600160381b90910481169086161115611c87576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b8854600090611ca290600160381b900462ffffff1683611b4f565b8a54909150600160381b900462ffffff9081169087166002021115611ce6578954600160381b900462ffffff9081169087166002020380821015611ce4578091505b505b8954600160381b900462ffffff16811115611d31576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b895463ffffffff90811690881610801590611d5957508954600160201b900462ffffff168111155b15611dbf57895460408a015160208b015163ffffffff8316975060029091026001600160601b0390811692600160381b810462ffffff908116600160201b9092041601911687020281611da857fe5b8b5463ffffffff19168c5504935061232392505050565b895460208a015160009162ffffff600160381b82041684900391869163ffffffff1683026001600160601b039091160281611df657fe5b0491505089604001516002026001600160601b0316828c60000160079054906101000a900462ffffff1662ffffff1601600101820281611e3257fe5b0494506000611e5f828c602001516001600160601b03168b63ffffffff1602611b4f90919063ffffffff16565b60208c01518d5491925060009187916001600160601b031663ffffffff9091160281611e8757fe5b04905080821115611e96578091505b508a602001516001600160601b031681830181611eaf57fe5b049650611ed4828c602001516001600160601b03168902611b4f90919063ffffffff16565b9050611efa8b604001516001600160601b031684830281611ef157fe5b88919004611aa6565b60208c01518d54919750600093506001600160601b03169150611f289063ffffffff908116908990611b4f16565b60408c01518d5460208e01519290930292611f7a92600160381b820462ffffff908116600160201b840491909116016001600160601b0391821663ffffffff93841602029260020216890290611b4f16565b81611f8157fe5b8c549190049150611f9f908290600160201b900462ffffff16611b4f565b8b54909150600160201b900462ffffff16811015611ff5576040805162461bcd60e51b815260206004820152600e60248201526d2162616446696e616c52616e676560901b604482015290519081900360640190fd5b8a5462ffffff60381b1916600160381b62ffffff83160217808c556120259063ffffffff908116908890611b4f16565b8b5463ffffffff191663ffffffff91909116178b55506123209050565b885462ffffff600160201b90910481169086161015612091576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b88546000906120ac90600160201b900462ffffff1683611aa6565b8a549091506000906120d09062ffffff89811660020291600160201b900416611b4f565b9050808211156120de578091505b508954600160201b900462ffffff1681101561212a576040805162461bcd60e51b815260206004820152600660248201526521707269636560d01b604482015290519081900360640190fd5b895463ffffffff9081169088161080159061215257508954600160381b900462ffffff168110155b156121a157895460408a015160208b015163ffffffff8316975060029091026001600160601b0390811692600160381b810462ffffff908116600160201b9092041601911687020281611da857fe5b895460208a015160009162ffffff600160201b820416840391869163ffffffff1683026001600160601b0390911602816121d757fe5b0491505089604001516002026001600160601b03166001838d60000160049054906101000a900462ffffff1662ffffff16010382028161221357fe5b0494506000612240828c602001516001600160601b03168b63ffffffff1602611b4f90919063ffffffff16565b60208c01518d5491925060009187916001600160601b031663ffffffff909116028161226857fe5b04905080821115612277578091505b508a602001516001600160601b03168183018161229057fe5b0496506122b5828c602001516001600160601b03168902611b4f90919063ffffffff16565b90506122d28b604001516001600160601b031684830281611ef157fe5b8c549096506122ee925063ffffffff90811691508790611b4f16565b8a5463ffffffff191663ffffffff919091161766ffffff000000001916600160201b62ffffff92909216919091021789555b50505b9550959350505050565b61233f826001600160a01b03166124e5565b612390576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106123ce5780518252601f1990920191602091820191016123af565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612430576040519150601f19603f3d011682016040523d82523d6000602084013e612435565b606091505b50915091508161248c576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b49578080602001905160208110156124a857600080fd5b5051611b495760405162461bcd60e51b815260040180806020018281038252602a815260200180612549602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906125195750808214155b949350505050565b6040805160808101825260008082526020820181905291810182905260608101919091529056fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122027db567a69e2cd1271882b6301e44f31d93acaf01e6542df89ba27456154205164736f6c634300060c0033

Verified Source Code Partial Match

Compiler: v0.6.12+commit.27d51765 EVM: istanbul Optimization: Yes (200 runs)
KittenSwapV01.sol 542 lines
//   _    _ _   _                __ _                            
//  | |  (_) | | |              / _(_)                           
//  | | ___| |_| |_ ___ _ __   | |_ _ _ __   __ _ _ __   ___ ___ 
//  | |/ / | __| __/ _ \ '_ \  |  _| | '_ \ / _` | '_ \ / __/ _ \
//  |   <| | |_| ||  __/ | | |_| | | | | | | (_| | | | | (_|  __/
//  |_|\_\_|\__|\__\___|_| |_(_)_| |_|_| |_|\__,_|_| |_|\___\___|
//
//  KittenSwap v0.1
//
//  https://www.KittenSwap.org/
//
pragma solidity ^0.6.12;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "!!add");
        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "!!sub");
        uint256 c = a - b;
        return c;
    }
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "!!mul");
        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "!!div");
        uint256 c = a / b;
        return c;
    }
}

interface IERC20 {
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

library Address {
    function isContract(address account) internal view returns (bool) {
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != 0x0 && codehash != accountHash);
    }
}

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 callOptionalReturn(IERC20 token, bytes memory data) private {
        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");
        }
    }
}

////////////////////////////////////////////////////////////////////////////////

contract KittenSwapV01 
{
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    
    ////////////////////////////////////////////////////////////////////////////////
    
    address public govAddr;
    address public devAddr;
    
    constructor () public {
        govAddr = msg.sender;
        devAddr = msg.sender;
    }
    
    modifier govOnly() 
    {
    	require(msg.sender == govAddr, "!gov");
    	_;
    }
    function govTransferAddr(address newAddr) external govOnly 
    {
    	require(newAddr != address(0), "!addr");
    	govAddr = newAddr;
    }
    
    modifier devOnly() 
    {
    	require(msg.sender == devAddr, "!dev");
    	_;
    }
    function devTransferAddr(address newAddr) external govOnly 
    {
    	require(newAddr != address(0), "!addr");
    	devAddr = newAddr;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    mapping (address => mapping (address => uint)) public vault;
    
    event VAULT_DEPOSIT(address indexed user, address indexed token, uint amt);
    event VAULT_WITHDRAW(address indexed user, address indexed token, uint amt);
    
    function vaultWithdraw(address token, uint amt) external 
    {
        address payable user = msg.sender;

        vault[user][token] = vault[user][token].sub(amt);
        if (token == address(0)) {
            user.transfer(amt);
        } else {
            IERC20(token).safeTransfer(user, amt);
        }
        emit VAULT_WITHDRAW(user, token, amt);
    }
    
    function vaultDeposit(address token, uint amt) external payable
    {
        address user = msg.sender;

        if (token == address(0)) {
            vault[user][token] = vault[user][token].add(msg.value);
        } else {
            IERC20(token).safeTransferFrom(user, address(this), amt);
            vault[user][token] = vault[user][token].add(amt);
        }
        emit VAULT_DEPOSIT(user, token, amt);
    }    
    
    ////////////////////////////////////////////////////////////////////////////////
    
    struct MARKET {
        address token;        // fixed after creation
        uint96 AMT_SCALE;     // fixed after creation
        uint96 PRICE_SCALE;   // fixed after creation
        uint16 DEVFEE_BP;     // in terms of basis points (1 bp = 0.01%)
    }
    MARKET[] public marketList;
    
    event MARKET_CREATE(address indexed token, uint96 $AMT_SCALE, uint96 $PRICE_SCALE, uint indexed id);
    
    function govCreateMarket(address $token, uint96 $AMT_SCALE, uint96 $PRICE_SCALE, uint16 $DEVFEE_BP) external govOnly 
    {
        require ($AMT_SCALE > 0);
        require ($PRICE_SCALE > 0);
        require ($DEVFEE_BP <= 60);
        
        MARKET memory m;
        m.token = $token;
        m.AMT_SCALE = $AMT_SCALE;
        m.PRICE_SCALE = $PRICE_SCALE;
        m.DEVFEE_BP = $DEVFEE_BP;
        
        marketList.push(m);
        
        emit MARKET_CREATE($token, $AMT_SCALE, $PRICE_SCALE, marketList.length - 1);
    }
    
    function govSetDevFee(uint $marketId, uint16 $DEVFEE_BP) external govOnly 
    {
        require ($DEVFEE_BP <= 60);
        marketList[$marketId].DEVFEE_BP = $DEVFEE_BP;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    struct ORDER {
        uint32 tokenAmtScaled;  // scaled by AMT_SCALE        SCALE 10^12 => 1 ~ 2^32-1 means 0.000001 ~ 4294.967295
        uint24 priceLowScaled;  // scaled by PRICE_SCALE      SCALE 10^4 => 1 ~ 2^24-1 means 0.0001 ~ 1677.7215
        uint24 priceHighScaled; // scaled by PRICE_SCALE      SCALE 10^4 => 1 ~ 2^24-1 means 0.0001 ~ 1677.7215
        uint160 userMaker;
    }
    mapping (uint => ORDER[]) public orderList; // div 2 = market, mod 2 = 0 sell, 1 buy
    
    uint constant UINT32_MAX = 2**32 - 1;
    
    event ORDER_CREATE(address indexed userMaker, uint indexed marketIsBuy, uint orderInfo, uint indexed orderId);
    event ORDER_MODIFY(address indexed userMaker, uint indexed marketIsBuy, uint newOrderInfo, uint indexed orderId);
    event ORDER_TRADE(address indexed userTaker, address userMaker, uint indexed marketIsBuy, uint fillOrderInfo, uint indexed orderId);

    ////////////////////////////////////////////////////////////////////////////////
    
    function marketCount() external view returns (uint)
    {
        return marketList.length;
    }
    
    function orderCount(uint $marketIsBuy) external view returns (uint)
    {
        return orderList[$marketIsBuy].length;
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    function orderCreate(uint $marketIsBuy, uint32 $tokenAmtScaled, uint24 $priceLowScaled, uint24 $priceHighScaled) external payable 
    {
        require($priceLowScaled > 0, "!priceLow");
        require($priceHighScaled > 0, "!priceHigh");
        require($priceHighScaled >= $priceLowScaled, "!priceRange");

        uint isMakerBuy = $marketIsBuy % 2;
        MARKET memory m = marketList[$marketIsBuy / 2];
        require(m.token != address(0), "!market");
        
        //------------------------------------------------------------------------------

        address userMaker = msg.sender;
            
        if (isMakerBuy > 0) // buy token -> deposit ETH
        {
            uint ethAmt = uint($tokenAmtScaled) * uint(m.AMT_SCALE) * (uint($priceLowScaled) + uint($priceHighScaled)) / uint(m.PRICE_SCALE * 2);
            require(msg.value == ethAmt, '!eth');
        }
        else // sell token -> deposit token
        {
            IERC20 token = IERC20(m.token);
            if ($tokenAmtScaled > 0)
                token.safeTransferFrom(userMaker, address(this), uint($tokenAmtScaled) * uint(m.AMT_SCALE));
            require(msg.value == 0, '!eth');
        }
        
        //------------------------------------------------------------------------------
        
        ORDER memory o;
        o.userMaker = uint160(userMaker);
        o.tokenAmtScaled = $tokenAmtScaled;
        o.priceLowScaled = $priceLowScaled;
        o.priceHighScaled = $priceHighScaled;
        
        //------------------------------------------------------------------------------

        ORDER[] storage oList = orderList[$marketIsBuy];
        oList.push(o);
        
        uint orderId = oList.length - 1;
        uint orderInfo = $tokenAmtScaled | ($priceLowScaled<<32) | ($priceHighScaled<<(32+24));

        emit ORDER_CREATE(userMaker, $marketIsBuy, orderInfo, orderId);
    }

    ////////////////////////////////////////////////////////////////////////////////
    
    function orderModify(uint $marketIsBuy, uint32 newTokenAmtScaled, uint24 newPriceLowScaled, uint24 newPriceHighScaled, uint orderID) external payable 
    {
        require(newPriceLowScaled > 0, "!priceLow");
        require(newPriceHighScaled > 0, "!priceHigh");
        require(newPriceHighScaled >= newPriceLowScaled, "!priceRange");
        
        address payable userMaker = msg.sender;
        ORDER storage o = orderList[$marketIsBuy][orderID];
        require (uint160(userMaker) == o.userMaker, "!user");

        uint isMakerBuy = $marketIsBuy % 2;
        MARKET memory m = marketList[$marketIsBuy / 2];
        
        //------------------------------------------------------------------------------

        if (isMakerBuy > 0) // old order: maker buy token -> modify ETH amt
        {
            uint oldEthAmt = uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) * (uint(o.priceLowScaled) + uint(o.priceHighScaled)) / uint(m.PRICE_SCALE * 2);
            uint newEthAmt = uint(newTokenAmtScaled) * uint(m.AMT_SCALE) * (uint(newPriceLowScaled) + uint(newPriceHighScaled)) / uint(m.PRICE_SCALE * 2);

            uint extraEthAmt = (msg.value).add(oldEthAmt).sub(newEthAmt); // throw if not enough
            
            if (extraEthAmt > 0)
                userMaker.transfer(extraEthAmt); // return extra ETH to maker
        }
        else // old order: maker sell token -> modify token amt
        {
            uint oldTokenAmt = uint(o.tokenAmtScaled) * uint(m.AMT_SCALE);
            uint newTokenAmt = uint(newTokenAmtScaled) * uint(m.AMT_SCALE);

            IERC20 token = IERC20(m.token);
            if (newTokenAmt > oldTokenAmt) {
                token.safeTransferFrom(userMaker, address(this), newTokenAmt - oldTokenAmt);
            }
            else if (newTokenAmt < oldTokenAmt) {
                token.safeTransfer(userMaker, oldTokenAmt - newTokenAmt); // return extra token to maker
            }
            require(msg.value == 0, '!eth');            
        }
        
        //------------------------------------------------------------------------------
        
        if (o.tokenAmtScaled != newTokenAmtScaled)
            o.tokenAmtScaled = newTokenAmtScaled;
        if (o.priceLowScaled != newPriceLowScaled)
            o.priceLowScaled = newPriceLowScaled;
        if (o.priceHighScaled != newPriceHighScaled)
            o.priceHighScaled = newPriceHighScaled;

        uint orderInfo = newTokenAmtScaled | (newPriceLowScaled<<32) | (newPriceHighScaled<<(32+24));

        emit ORDER_MODIFY(userMaker, $marketIsBuy, orderInfo, orderID);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    
    
    function _fill_WLO(ORDER storage o, MARKET memory m, uint isMakerBuy, uint32 $tokenAmtScaled, uint24 fillPriceWorstScaled) internal returns (uint fillTokenAmtScaled, uint fillEthAmt)
    {
        uint allSlots = uint(1) + uint(o.priceHighScaled) - uint(o.priceLowScaled);
        uint fullFillSlots = allSlots * ($tokenAmtScaled) / uint(o.tokenAmtScaled);
        if (fullFillSlots > allSlots) {
            fullFillSlots = allSlots;
        }
        
        if (isMakerBuy > 0) // maker buy token -> taker sell token
        {
            require (fillPriceWorstScaled <= o.priceHighScaled, '!price');
            uint fillPriceEndScaled = uint(o.priceHighScaled).sub(fullFillSlots);
            if ((uint(fillPriceWorstScaled) * 2) > (o.priceHighScaled))
            {
                uint _ppp = (uint(fillPriceWorstScaled) * 2) - (o.priceHighScaled);
                if (fillPriceEndScaled < _ppp)
                    fillPriceEndScaled = _ppp;
            }
            require (fillPriceEndScaled <= o.priceHighScaled, '!price');
            
            //------------------------------------------------------------------------------
            
            if (($tokenAmtScaled >= o.tokenAmtScaled) && (fillPriceEndScaled <= o.priceLowScaled)) // full fill
            {
                fillTokenAmtScaled = o.tokenAmtScaled;
                fillEthAmt = uint(fillTokenAmtScaled) * uint(m.AMT_SCALE) * (uint(o.priceLowScaled) + uint(o.priceHighScaled)) / uint(m.PRICE_SCALE * 2);

                o.tokenAmtScaled = 0;

                return (fillTokenAmtScaled, fillEthAmt);
            }
            
            //------------------------------------------------------------------------------
            
            {
                uint fillTokenAmtFirst = 0; // full fill @ [fillPriceEndScaled+1, priceHighScaled]
                {
                    uint firstFillSlots = uint(o.priceHighScaled) - uint(fillPriceEndScaled);
                    fillTokenAmtFirst = firstFillSlots * uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) / allSlots;
                }
                fillEthAmt = fillTokenAmtFirst * (uint(o.priceHighScaled) + uint(fillPriceEndScaled) + 1) / uint(m.PRICE_SCALE * 2);
                
                uint fillTokenAmtSecond = (uint($tokenAmtScaled) * uint(m.AMT_SCALE)).sub(fillTokenAmtFirst); // partial fill @ fillPriceEndScaled
                {
                    uint amtPerSlot = uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) / allSlots;
                    if (fillTokenAmtSecond > amtPerSlot) {
                        fillTokenAmtSecond = amtPerSlot;
                    }
                }
                
                fillTokenAmtScaled = (fillTokenAmtFirst + fillTokenAmtSecond) / uint(m.AMT_SCALE);
                
                fillTokenAmtSecond = (fillTokenAmtScaled * uint(m.AMT_SCALE)).sub(fillTokenAmtFirst);
                fillEthAmt = fillEthAmt.add(fillTokenAmtSecond * fillPriceEndScaled / uint(m.PRICE_SCALE));
            }
            
            //------------------------------------------------------------------------------
            
            uint newPriceHighScaled =
                (
                    ( uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) * (uint(o.priceLowScaled) + uint(o.priceHighScaled)) )
                    .sub
                    ( fillEthAmt * uint(m.PRICE_SCALE * 2) )
                )
                /
                ( (uint(o.tokenAmtScaled).sub(fillTokenAmtScaled)) * uint(m.AMT_SCALE) )
            ;
            newPriceHighScaled = newPriceHighScaled.sub(o.priceLowScaled);
            
            require (newPriceHighScaled >= o.priceLowScaled, "!badFinalRange"); // shall never happen
            
            o.priceHighScaled = uint24(newPriceHighScaled);        
            
            o.tokenAmtScaled = uint32(uint(o.tokenAmtScaled).sub(fillTokenAmtScaled));
        }
        //------------------------------------------------------------------------------
        else // maker sell token -> taker buy token
        {
            require (fillPriceWorstScaled >= o.priceLowScaled, '!price');
            uint fillPriceEndScaled = uint(o.priceLowScaled).add(fullFillSlots);
            {
                uint _ppp = (uint(fillPriceWorstScaled) * 2).sub(o.priceLowScaled);
                if (fillPriceEndScaled > _ppp)
                    fillPriceEndScaled = _ppp;
            }
            require (fillPriceEndScaled >= o.priceLowScaled, '!price');
            
            //------------------------------------------------------------------------------
            
            if (($tokenAmtScaled >= o.tokenAmtScaled) && (fillPriceEndScaled >= o.priceHighScaled)) // full fill
            {
                fillTokenAmtScaled = o.tokenAmtScaled;
                fillEthAmt = uint(fillTokenAmtScaled) * uint(m.AMT_SCALE) * (uint(o.priceLowScaled) + uint(o.priceHighScaled)) / uint(m.PRICE_SCALE * 2);

                o.tokenAmtScaled = 0;

                return (fillTokenAmtScaled, fillEthAmt);
            }
            
            //------------------------------------------------------------------------------

            {
                uint fillTokenAmtFirst = 0; // full fill @ [priceLowScaled, fillPriceEndScaled-1]
                {
                    uint firstFillSlots = uint(fillPriceEndScaled) - uint(o.priceLowScaled);
                    fillTokenAmtFirst = firstFillSlots * uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) / allSlots;
                }
                fillEthAmt = fillTokenAmtFirst * (uint(o.priceLowScaled) + uint(fillPriceEndScaled) - 1) / uint(m.PRICE_SCALE * 2);
                
                uint fillTokenAmtSecond = (uint($tokenAmtScaled) * uint(m.AMT_SCALE)).sub(fillTokenAmtFirst); // partial fill @ fillPriceEndScaled
                {
                    uint amtPerSlot = uint(o.tokenAmtScaled) * uint(m.AMT_SCALE) / allSlots;
                    if (fillTokenAmtSecond > amtPerSlot) {
                        fillTokenAmtSecond = amtPerSlot;
                    }
                }
                
                fillTokenAmtScaled = (fillTokenAmtFirst + fillTokenAmtSecond) / uint(m.AMT_SCALE);
                
                fillTokenAmtSecond = (fillTokenAmtScaled * uint(m.AMT_SCALE)).sub(fillTokenAmtFirst);
                fillEthAmt = fillEthAmt.add(fillTokenAmtSecond * fillPriceEndScaled / uint(m.PRICE_SCALE));
            }
            
            //------------------------------------------------------------------------------
            
            o.tokenAmtScaled = uint32(uint(o.tokenAmtScaled).sub(fillTokenAmtScaled));
            o.priceLowScaled = uint24(fillPriceEndScaled);
        }
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    function orderTrade(uint $marketIsBuy, uint32 $tokenAmtScaled, uint24 fillPriceWorstScaled, uint orderID) external payable 
    {
        ORDER storage o = orderList[$marketIsBuy][orderID];
        require ($tokenAmtScaled > 0, '!amt');
        require (o.tokenAmtScaled > 0, '!amt');

        address payable userTaker = msg.sender;
        address payable userMaker = payable(o.userMaker);

        uint isMakerBuy = $marketIsBuy % 2;
        MARKET memory m = marketList[$marketIsBuy / 2];
        IERC20 token = IERC20(m.token);

        uint fillTokenAmtScaled = 0;
        uint fillEthAmt = 0;
        
        //------------------------------------------------------------------------------

        if (o.priceLowScaled == o.priceHighScaled) // simple limit order
        {
            uint fillPriceScaled = o.priceLowScaled;
            
            if (isMakerBuy > 0) { // maker buy token -> taker sell token
                require (fillPriceScaled >= fillPriceWorstScaled, "!price"); // sell at higher price
            }
            else { // maker sell token -> taker buy token
                require (fillPriceScaled <= fillPriceWorstScaled, "!price"); // buy at lower price
            }
            
            //------------------------------------------------------------------------------

            fillTokenAmtScaled = $tokenAmtScaled;
            if (fillTokenAmtScaled > o.tokenAmtScaled)
                fillTokenAmtScaled = o.tokenAmtScaled;

            fillEthAmt = fillTokenAmtScaled * uint(m.AMT_SCALE) * (fillPriceScaled) / uint(m.PRICE_SCALE);

            o.tokenAmtScaled = uint32(uint(o.tokenAmtScaled).sub(fillTokenAmtScaled));
        }
        //------------------------------------------------------------------------------
        else // Wide Limit Order
        {
            require (o.priceHighScaled > o.priceLowScaled, '!badOrder');
            
            (fillTokenAmtScaled, fillEthAmt) = _fill_WLO(o, m, isMakerBuy, $tokenAmtScaled, fillPriceWorstScaled); // will modify order
        }
        
        //------------------------------------------------------------------------------
        
        require(fillTokenAmtScaled > 0, "!fillTokenAmtScaled");
        require(fillEthAmt > 0, "!fillEthAmt");
        
        uint fillTokenAmt = fillTokenAmtScaled * uint(m.AMT_SCALE);
        
        if (isMakerBuy > 0) // maker buy token -> taker sell token
        {
            token.safeTransferFrom(userTaker, userMaker, fillTokenAmt); // send token to maker (from taker)

            uint devFee = fillEthAmt * uint(m.DEVFEE_BP) / (10000);
            vault[devAddr][address(0)] = vault[devAddr][address(0)].add(devFee);

            userTaker.transfer(fillEthAmt.sub(devFee)); // send eth to taker
            require(msg.value == 0, '!eth');
        }
        else // maker sell token -> taker buy token
        {
            require(msg.value >= fillEthAmt, '!eth');
            
            token.safeTransfer(userTaker, fillTokenAmt); // send token to taker

            uint devFee = fillEthAmt * uint(m.DEVFEE_BP) / (10000);
            vault[devAddr][address(0)] = vault[devAddr][address(0)].add(devFee);

            userMaker.transfer(fillEthAmt.sub(devFee)); // send eth to maker
            
            if (msg.value > fillEthAmt) {
                userTaker.transfer(msg.value - fillEthAmt); // return extra eth to taker
            }
        }

        //------------------------------------------------------------------------------

        uint orderInfo = fillTokenAmtScaled | fillEthAmt<<32;

        emit ORDER_TRADE(userTaker, userMaker, $marketIsBuy, orderInfo, orderID);    
    }
}

Read Contract

devAddr 0xda09c72c → address
govAddr 0xcb85ce67 → address
marketCount 0xec979082 → uint256
marketList 0x232b956c → address, uint96, uint96, uint16
orderCount 0x33763d9a → uint256
orderList 0xc1ec95c0 → uint32, uint24, uint24, uint160
vault 0x1b54cc88 → uint256

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

devTransferAddr 0xd7628cb9
address newAddr
govCreateMarket 0x97cf5e85
address $token
uint96 $AMT_SCALE
uint96 $PRICE_SCALE
uint16 $DEVFEE_BP
govSetDevFee 0x79c7ba5d
uint256 $marketId
uint16 $DEVFEE_BP
govTransferAddr 0x42edd8e0
address newAddr
orderCreate 0x5bdc609b
uint256 $marketIsBuy
uint32 $tokenAmtScaled
uint24 $priceLowScaled
uint24 $priceHighScaled
orderModify 0xa0eefff0
uint256 $marketIsBuy
uint32 newTokenAmtScaled
uint24 newPriceLowScaled
uint24 newPriceHighScaled
uint256 orderID
orderTrade 0xc717978f
uint256 $marketIsBuy
uint32 $tokenAmtScaled
uint24 fillPriceWorstScaled
uint256 orderID
vaultDeposit 0x042bbe3a
address token
uint256 amt
vaultWithdraw 0x0fe31eb1
address token
uint256 amt

Recent Transactions

No transactions found for this address