Address Contract Partially Verified
Address
0x097B3B7CB01945ba7e76804DDC2fddA2Cce6EF43
Balance
0 ETH
Nonce
1
Code Size
12442 bytes
Creator
0x956C88eC...cd15 at tx 0xbd0aef37...dee193
Indexed Transactions
0 (1 on-chain, 0.9% indexed)
Contract Bytecode
12442 bytes
0x6060604052600436106101a85763ffffffff60e060020a60003504166301a12fd381146101ad57806314673d31146101ce578063158859f7146101ed578063162656941461020c5780631a4813d7146102315780631d6a8bda146103c957806326782247146103e857806327a099d8146104175780632ba996a51461047d5780633ccdbb2814610490578063408ee7fe146104b95780635085c9f1146104d857806362674e93146104eb57806364887334146105105780636c6295b8146105e8578063721bba59146105fe57806375829def1461063957806377f50f97146106585780637acc86781461066b5780637c423f541461068a5780638036d7571461069d57806380d8b380146106bc5780639870d7fe146107d9578063a7f43acd146107f8578063a80c609e1461080b578063ac8a584a1461082d578063b8e9c22e1461084c578063bc9cbcc814610876578063bfee356914610993578063c6fd2103146109bb578063ce56c454146109e3578063cf8fee1114610a05578063d48bfca714610a29578063e4a2ac6214610a48578063e7d4fd9114610ab6578063f851a44014610af9575b600080fd5b34156101b857600080fd5b6101cc600160a060020a0360043516610b0c565b005b34156101d957600080fd5b6101cc600160a060020a0360043516610c7c565b34156101f857600080fd5b6101cc600160a060020a0360043516610cb9565b341561021757600080fd5b61021f610d29565b60405190815260200160405180910390f35b341561023c57600080fd5b6101cc60046024813581810190830135806020818102016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843750949650610d2f95505050505050565b34156103d457600080fd5b6101cc600160a060020a0360043516610e95565b34156103f357600080fd5b6103fb610f21565b604051600160a060020a03909116815260200160405180910390f35b341561042257600080fd5b61042a610f30565b60405160208082528190810183818151815260200191508051906020019060200280838360005b83811015610469578082015183820152602001610451565b505050509050019250505060405180910390f35b341561048857600080fd5b61042a610f99565b341561049b57600080fd5b6101cc600160a060020a036004358116906024359060443516610fff565b34156104c457600080fd5b6101cc600160a060020a03600435166110f6565b34156104e357600080fd5b61021f6111f2565b34156104f657600080fd5b61021f600160a060020a03600435166024356044356111f8565b341561051b57600080fd5b6101cc600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437509496506114ec95505050505050565b34156105f357600080fd5b6101cc60043561162d565b341561060957600080fd5b61061d600160a060020a036004351661164d565b6040519115158252151560208201526040908101905180910390f35b341561064457600080fd5b6101cc600160a060020a0360043516611675565b341561066357600080fd5b6101cc611710565b341561067657600080fd5b6101cc600160a060020a03600435166117aa565b341561069557600080fd5b61042a61188c565b34156106a857600080fd5b61021f600160a060020a03600435166118f2565b34156106c757600080fd5b6101cc60048035600160a060020a031690604460248035908101908301358060208082020160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284375094965061193d95505050505050565b34156107e457600080fd5b6101cc600160a060020a0360043516611a85565b341561080357600080fd5b6103fb611b55565b341561081657600080fd5b61021f600160a060020a0360043516602435611b64565b341561083857600080fd5b6101cc600160a060020a0360043516611b81565b341561085757600080fd5b61021f600160a060020a03600435166024356044351515606435611ced565b341561088157600080fd5b6101cc60048035600160a060020a031690604460248035908101908301358060208082020160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284375094965061228395505050505050565b341561099e57600080fd5b6101cc600160a060020a03600435166024356044356064356123b2565b34156109c657600080fd5b6101cc600160a060020a0360043516602435604435606435612420565b34156109ee57600080fd5b6101cc600435600160a060020a0360243516612460565b3415610a1057600080fd5b61021f600160a060020a036004351660243515156124f3565b3415610a3457600080fd5b6101cc600160a060020a0360043516612541565b3415610a5357600080fd5b610a67600160a060020a036004351661264e565b60405193845260208401929092527fff00000000000000000000000000000000000000000000000000000000000000908116604080850191909152911660608301526080909101905180910390f35b3415610ac157600080fd5b610ad5600160a060020a0360043516612712565b60405180848152602001838152602001828152602001935050505060405180910390f35b3415610b0457600080fd5b6103fb61273a565b6000805433600160a060020a03908116911614610b2857600080fd5b600160a060020a03821660009081526003602052604090205460ff161515610b4f57600080fd5b50600160a060020a0381166000908152600360205260408120805460ff191690555b600554811015610c785781600160a060020a0316600582815481101515610b9457fe5b600091825260209091200154600160a060020a03161415610c7057600580546000198101908110610bc157fe5b60009182526020909120015460058054600160a060020a039092169183908110610be757fe5b60009182526020909120018054600160a060020a031916600160a060020a03929092169190911790556005805490610c23906000198301612fa5565b507f5611bf3e417d124f97bf2c788843ea8bb502b66079fbee02158ef30b172cb762826000604051600160a060020a039092168252151560208201526040908101905180910390a1610c78565b600101610b71565b5050565b60005433600160a060020a03908116911614610c9757600080fd5b600e8054600160a060020a031916600160a060020a0392909216919091179055565b600160a060020a03331660009081526003602052604090205460ff161515610ce057600080fd5b600160a060020a0381166000908152600b602052604090205460ff161515610d0757600080fd5b600160a060020a03166000908152600b60205260409020805461ff0019169055565b60095481565b600160a060020a03331660009081526002602052604081205460ff161515610d5657600080fd5b8651885114610d6457600080fd5b8551885114610d7257600080fd5b8451845114610d8057600080fd5b8151845114610d8e57600080fd5b5060005b8751811015610e7f57600b6000898381518110610dab57fe5b90602001906020020151600160a060020a0316815260208101919091526040016000205460ff161515610ddd57600080fd5b868181518110610de957fe5b90602001906020020151600b60008a8481518110610e0357fe5b90602001906020020151600160a060020a03168152602081019190915260400160002060030155858181518110610e3657fe5b90602001906020020151600b60008a8481518110610e5057fe5b90602001906020020151600160a060020a03168152602081019190915260400160002060040155600101610d92565b610e8b858585856114ec565b5050505050505050565b60005433600160a060020a03908116911614610eb057600080fd5b600160a060020a0381166000908152600b602052604090205460ff161515610ed757600080fd5b600160a060020a0381166000908152600660205260409020541515610efb57600080fd5b600160a060020a03166000908152600b60205260409020805461ff001916610100179055565b600154600160a060020a031681565b610f38612fce565b6004805480602002602001604051908101604052809291908181526020018280548015610f8e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610f70575b505050505090505b90565b610fa1612fce565b600a805480602002602001604051908101604052809291908181526020018280548015610f8e57602002820191906000526020600020908154600160a060020a03168152600190910190602001808311610f70575050505050905090565b60005433600160a060020a0390811691161461101a57600080fd5b82600160a060020a031663a9059cbb828460006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561107757600080fd5b6102c65a03f1151561108857600080fd5b50505060405180519050151561109d57600080fd5b7f72cb8a894ddb372ceec3d2a7648d86f17d5a15caae0e986c53109b8a9a9385e6838383604051600160a060020a03938416815260208101929092529091166040808301919091526060909101905180910390a1505050565b60005433600160a060020a0390811691161461111157600080fd5b600160a060020a03811660009081526003602052604090205460ff161561113757600080fd5b6005546032901061114757600080fd5b7f5611bf3e417d124f97bf2c788843ea8bb502b66079fbee02158ef30b172cb762816001604051600160a060020a039092168252151560208201526040908101905180910390a1600160a060020a0381166000908152600360205260409020805460ff1916600190811790915560058054909181016111c68382612fa5565b5060009182526020909120018054600160a060020a031916600160a060020a0392909216919091179055565b600d5481565b60008215156112235750600160a060020a0383166000908152600b60205260409020600501546114e5565b826001141561126657600160a060020a0384166000908152600b6020526040902060050180548390811061125357fe5b90600052602060002090015490506114e5565b82600214156112915750600160a060020a0383166000908152600b60205260409020600601546114e5565b82600314156112c157600160a060020a0384166000908152600b6020526040902060060180548390811061125357fe5b82600414156112ec5750600160a060020a0383166000908152600b60205260409020600701546114e5565b826005141561131c57600160a060020a0384166000908152600b6020526040902060070180548390811061125357fe5b82600614156113475750600160a060020a0383166000908152600b60205260409020600801546114e5565b826007141561137757600160a060020a0384166000908152600b6020526040902060080180548390811061125357fe5b82600814156113a25750600160a060020a0383166000908152600b60205260409020600901546114e5565b82600914156113d257600160a060020a0384166000908152600b6020526040902060090180548390811061125357fe5b82600a14156113fd5750600160a060020a0383166000908152600b60205260409020600a01546114e5565b82600b141561142d57600160a060020a0384166000908152600b60205260409020600a0180548390811061125357fe5b82600c14156114595750600160a060020a0383166000908152600b6020819052604090912001546114e5565b82600d141561148a57600160a060020a0384166000908152600b602081905260409091200180548390811061125357fe5b82600e14156114b55750600160a060020a0383166000908152600b60205260409020600c01546114e5565b82600f14156101a857600160a060020a0384166000908152600b60205260409020600c0180548390811061125357fe5b9392505050565b600160a060020a0333166000908152600260205260408120548190819060ff16151561151757600080fd5b855187511461152557600080fd5b865184511461153357600080fd5b63ffffffff85111561154457600080fd5b6e0100000000000000000000000000009250600091505b835182101561162457600c5484838151811061157357fe5b906020019060200201511061158757600080fd5b82830285028387848151811061159957fe5b9060200190602002015172010000000000000000000000000000000000009004028884815181106115c657fe5b90602001906020020151720100000000000000000000000000000000000090041717905080600c8584815181106115f957fe5b906020019060200201518154811061160d57fe5b60009182526020909120015560019091019061155b565b50505050505050565b60005433600160a060020a0390811691161461164857600080fd5b600955565b600160a060020a03166000908152600b602052604090205460ff808216926101009092041690565b60005433600160a060020a0390811691161461169057600080fd5b600160a060020a03811615156116a557600080fd5b6001547f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc4090600160a060020a0316604051600160a060020a03909116815260200160405180910390a160018054600160a060020a031916600160a060020a0392909216919091179055565b60015433600160a060020a0390811691161461172b57600080fd5b6001546000547f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed91600160a060020a039081169116604051600160a060020a039283168152911660208201526040908101905180910390a16001805460008054600160a060020a0319908116600160a060020a03841617909155169055565b60005433600160a060020a039081169116146117c557600080fd5b600160a060020a03811615156117da57600080fd5b7f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc4081604051600160a060020a03909116815260200160405180910390a16000547f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed908290600160a060020a0316604051600160a060020a039283168152911660208201526040908101905180910390a160008054600160a060020a031916600160a060020a0392909216919091179055565b611894612fce565b6005805480602002602001604051908101604052809291908181526020018280548015610f8e57602002820191906000526020600020908154600160a060020a03168152600190910190602001808311610f70575050505050905090565b600160a060020a0381166000908152600b6020526040812060010154600c8054839290811061191d57fe5b906000526020600020900154905061193481612749565b91505b50919050565b600160a060020a03331660009081526002602052604090205460ff16151561196457600080fd5b825184511461197257600080fd5b805182511461198057600080fd5b600a8451111561198f57600080fd5b600a8251111561199e57600080fd5b600160a060020a0385166000908152600b602052604090205460ff1615156119c557600080fd5b6040805190810160409081528582526020808301869052600160a060020a0388166000908152600b90915220600501815181908051611a08929160200190612fe0565b50602082015181600101908051611a23929160200190612fe0565b509050506040805190810160409081528382526020808301849052600160a060020a0388166000908152600b90915220600701815181908051611a6a929160200190612fe0565b50602082015181600101908051610e8b929160200190612fe0565b60005433600160a060020a03908116911614611aa057600080fd5b600160a060020a03811660009081526002602052604090205460ff1615611ac657600080fd5b60045460329010611ad657600080fd5b7f091a7a4b85135fdd7e8dbc18b12fabe5cc191ea867aa3c2e1a24a102af61d58b816001604051600160a060020a039092168252151560208201526040908101905180910390a1600160a060020a0381166000908152600260205260409020805460ff1916600190811790915560048054909181016111c68382612fa5565b600e54600160a060020a031681565b600760209081526000928352604080842090915290825290205481565b6000805433600160a060020a03908116911614611b9d57600080fd5b600160a060020a03821660009081526002602052604090205460ff161515611bc457600080fd5b50600160a060020a0381166000908152600260205260408120805460ff191690555b600454811015610c785781600160a060020a0316600482815481101515611c0957fe5b600091825260209091200154600160a060020a03161415611ce557600480546000198101908110611c3657fe5b60009182526020909120015460048054600160a060020a039092169183908110611c5c57fe5b60009182526020909120018054600160a060020a031916600160a060020a0392909216919091179055600480546000190190611c989082612fa5565b507f091a7a4b85135fdd7e8dbc18b12fabe5cc191ea867aa3c2e1a24a102af61d58b826000604051600160a060020a039092168252151560208201526040908101905180910390a1610c78565b600101611be6565b600160a060020a0384166000908152600b602052604081205481908190819081908190819081908190610100900460ff161515611d2d5760009850612273565b600160a060020a038d166000908152600660205260409020541515611d555760009850612273565b600160a060020a038d166000908152600b6020526040902060010154600c80549091908110611d8057fe5b9060005260206000209001549750611d9788612749565b60095490975087018c10611dae5760009850612273565b611db98d888e612756565b90965094508a15611ffd5750600160a060020a038c166000908152600b6020526040902060030154611ded888e600161278b565b91508160000b600a029250611e0281846127e4565b9050611e0f8d828c612830565b600160a060020a038e166000908152600b602052604090819020919b50968b01968b9550611efa91600501908051908101604052908160008201805480602002602001604051908101604052809291908181526020018280548015611e9357602002820191906000526020600020905b815481526020019060010190808311611e7f575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015611eeb57602002820191906000526020600020905b815481526020019060010190808311611ed7575b5050505050815250508b61285a565b9250611f0681846127e4565b600160a060020a038e166000908152600b602052604090819020919250611fea91600901908051908101604052908160008201805480602002602001604051908101604052809291908181526020018280548015611f8357602002820191906000526020600020905b815481526020019060010190808311611f6f575b5050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015611fdb57602002820191906000526020600020905b815481526020019060010190808311611fc7575b5050505050815250508761285a565b9250611ff681846127e4565b905061222d565b50600160a060020a038c166000908152600b6020526040812060040154906120289089908f9061278b565b91508160000b600a02925061203d81846127e4565b600160a060020a038e166000908152600b6020526040908190206000198d0298890198965091925061212891600701908051908101604052908160008201805480602002602001604051908101604052809291908181526020018280548015611e935760200282019190600052602060002090815481526020019060010190808311611e7f575050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015611eeb5760200282019190600052602060002090815481526020019060010190808311611ed7575050505050815250508b61285a565b925061213481846127e4565b905061221e600b60008f600160a060020a0316600160a060020a03168152602001908152602001600020600b0160408051908101604052908160008201805480602002602001604051908101604052809291908181526020018280548015611f835760200282019190600052602060002090815481526020019060010190808311611f6f575050505050815260200160018201805480602002602001604051908101604052809291908181526020018280548015611fdb5760200282019190600052602060002090815481526020019060010190808311611fc7575050505050815250508761285a565b925061222a81846127e4565b90505b6122368d6128e2565b61223f87612900565b1061224d5760009850612273565b6122568d61291c565b612261858701612900565b1061226f5760009850612273565b8098505b5050505050505050949350505050565b600160a060020a03331660009081526002602052604090205460ff1615156122aa57600080fd5b82518451146122b857600080fd5b80518251146122c657600080fd5b600a845111156122d557600080fd5b600a825111156122e457600080fd5b600160a060020a0385166000908152600b602052604090205460ff16151561230b57600080fd5b6040805190810160409081528582526020808301869052600160a060020a0388166000908152600b9091522060090181518190805161234e929160200190612fe0565b50602082015181600101908051612369929160200190612fe0565b509050506040805190810160409081528382526020808301849052600160a060020a0388166000908152600b918290529190912001815181908051611a6a929160200190612fe0565b60005433600160a060020a039081169116146123cd57600080fd5b606060405190810160409081528482526020808301859052818301849052600160a060020a0387166000908152600690915220815181556020820151816001015560408201516002909101555050505050565b600e5433600160a060020a0390811691161461243b57600080fd5b81151561244e5761244b846118f2565b91505b61245a8484848461293a565b50505050565b60005433600160a060020a0390811691161461247b57600080fd5b600160a060020a03811682156108fc0283604051600060405180830381858888f1935050505015156124ac57600080fd5b7fec47e7ed86c86774d1a72c19f35c639911393fe7c1a34031fdbd260890da90de8282604051918252600160a060020a031660208201526040908101905180910390a15050565b6000811561251d5750600160a060020a0382166000908152600b602052604090206003015461253b565b50600160a060020a0382166000908152600b60205260409020600401545b92915050565b60005433600160a060020a0390811691161461255c57600080fd5b600160a060020a0381166000908152600b602052604090205460ff161561258257600080fd5b600160a060020a0381166000908152600b60205260409020805460ff19166001908117909155600a8054909181016125ba8382612fa5565b5060009182526020909120018054600160a060020a031916600160a060020a038316179055600d5415156125fc57600c8054906125fa9060018301612fa5565b505b600c54600160a060020a0382166000908152600b60205260409020600019909101600182810191909155600d546002909201829055600e910106600d5561264281612a6a565b61264b81612aa5565b50565b600160a060020a0381166000908152600b60205260408120548190819081908190819060ff16151561267f57600080fd5b5050600160a060020a0385166000908152600b602052604090206001810154600290910154600c8054839183916126cf9190849081106126bb57fe5b9060005260206000209001548a600161278b565b60f860020a026126fb600c868154811015156126e757fe5b9060005260206000209001548b600061278b565b60f860020a02955095509550955050509193509193565b600160a060020a03166000908152600660205260409020805460018201546002909201549092565b600054600160a060020a031681565b60e060020a81045b919050565b600160a060020a038316600090815260066020526040812054819061277c868686612b67565b90820297910295509350505050565b600160a060020a0382166000908152600b60205260408120600201548183156127b85750601281016127be565b50600481015b8581602081106127ca57fe5b1a60f860020a0260f860020a900492505b50509392505050565b60008069d3c21bcecceda10000008411156127fe57600080fd5b61270f1983121561280e57600080fd5b64174876e80083131561282057600080fd5b5050612710908101919091020490565b600080600061283e86612c55565b91506012905061285085828487612d0f565b9695505050505050565b60008060008460200151519150600090505b818110156128ba578451818151811061288157fe5b9060200190602002015184136128b257846020015181815181106128a157fe5b9060200190602002015192506128da565b60010161286c565b846020015160018303815181106128cd57fe5b9060200190602002015192505b505092915050565b600160a060020a031660009081526006602052604090206002015490565b60008082121561291557506000198102612751565b5080612751565b600160a060020a031660009081526006602052604090206001015490565b600080600061294761302b565b600160a060020a0388166000908152600660205260408120546005870695508881151561297057fe5b600160a060020a038b1660009081526007602090815260408083208a845290915281205492909105955093506129a590612da8565b91508582602001511415612a045786826060015114156129d9578382818151019052508360408301818151019052506129ff565b6129e4898888612e35565b84810160408401529250838281815101905250606082018790525b612a2e565b612a0f898888612b67565b8584526020840188905260608401899052858201604085015290935090505b612a3782612ebd565b600160a060020a039099166000908152600760209081526040808320978352969052949094209790975550505050505050565b60005b6005811015610c7857600160a060020a0382166000908152600760209081526040808320848452909152902060019081905501612a6d565b600160a060020a03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612aeb57600160a060020a03811660009081526008602052604090206012905561264b565b80600160a060020a031663313ce5676000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612b3157600080fd5b6102c65a03f11515612b4257600080fd5b5050506040518051600160a060020a0383166000908152600860205260409020555050565b6000806000806000806000612b7a61302b565b60009750600096506000955060009450899350889250600091505b6005821015612c3c57600160a060020a038b166000908152600760209081526040808320858452909152902054612bcb90612da8565b905082816020015111158015612be5575083816020015110155b15612bf1578051850194505b89816060015114612c0157612c31565b8581602001511015612c1257612c31565b80602001519550806040015197508881602001511415612c3157805196505b600190910190612b95565b871515612c47578497505b505050505050935093915050565b600080600160a060020a03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612c865760129150611937565b50600160a060020a03821660009081526008602052604090205480151561253b5782600160a060020a031663313ce5676000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515612ced57600080fd5b6102c65a03f11515612cfe57600080fd5b505050604051805190509150611937565b60006b204fce5e3e25026110000000851115612d2a57600080fd5b69d3c21bcecceda1000000821115612d4157600080fd5b838310612d745760128484031115612d5857600080fd5b670de0b6b3a7640000858302858503600a0a025b049050612da0565b60128385031115612d8457600080fd5b828403600a0a670de0b6b3a764000002828602811515612d6c57fe5b949350505050565b612db061302b565b612db861302b565b67ffffffffffffffff83811660070b82526801000000000000000084041667ffffffffffffffff908116602083015270010000000000000000000000000000000084041660070b60408201527801000000000000000000000000000000000000000000000000830467ffffffffffffffff16606082015292915050565b600080612e4061302b565b83851115612e4d57600080fd5b60009250600091505b60058210156127db57600160a060020a0386166000908152600760209081526040808320858452909152902054612e8c90612da8565b905083816020015111158015612ea6575084816020015110155b15612eb2578051830192505b600190910190612e56565b600080678000000000000000835112612ed557600080fd5b677fffffffffffffff19835113612eeb57600080fd5b68010000000000000000836020015110612f0457600080fd5b678000000000000000604084015112612f1c57600080fd5b677fffffffffffffff19604084015113612f3557600080fd5b68010000000000000000836060015110612f4e57600080fd5b67ffffffffffffffff83511690506801000000000000000083602001510217680100000000000000008067ffffffffffffffff60408601511602021768010000000000000000808060608601510202021792915050565b815481835581811511612fc957600083815260209020612fc9918101908301613054565b505050565b60206040519081016040526000815290565b82805482825590600052602060002090810192821561301b579160200282015b8281111561301b578251825591602001919060010190613000565b50613027929150613054565b5090565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b610f9691905b80821115613027576000815560010161305a5600a165627a7a723058200ef3073f487bcdca36f37ac65d9b555ce0cd9a3d31ce3723d09d77bd9f8a42220029
Verified Source Code Partial Match
Compiler: v0.4.18+commit.9cf6e910
Optimization: Yes (200 runs)
ConversionRates.sol 802 lines
pragma solidity 0.4.18;
interface ConversionRatesInterface {
function recordImbalance(
ERC20 token,
int buyAmount,
uint rateUpdateBlock,
uint currentBlock
)
public;
function getRate(ERC20 token, uint currentBlockNumber, bool buy, uint qty) public view returns(uint);
}
interface ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf(address _owner) public view returns (uint balance);
function transfer(address _to, uint _value) public returns (bool success);
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
function approve(address _spender, uint _value) public returns (bool success);
function allowance(address _owner, address _spender) public view returns (uint remaining);
function decimals() public view returns(uint digits);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
contract PermissionGroups {
address public admin;
address public pendingAdmin;
mapping(address=>bool) internal operators;
mapping(address=>bool) internal alerters;
address[] internal operatorsGroup;
address[] internal alertersGroup;
uint constant internal MAX_GROUP_SIZE = 50;
function PermissionGroups() public {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin);
_;
}
modifier onlyOperator() {
require(operators[msg.sender]);
_;
}
modifier onlyAlerter() {
require(alerters[msg.sender]);
_;
}
function getOperators () external view returns(address[]) {
return operatorsGroup;
}
function getAlerters () external view returns(address[]) {
return alertersGroup;
}
event TransferAdminPending(address pendingAdmin);
/**
* @dev Allows the current admin to set the pendingAdmin address.
* @param newAdmin The address to transfer ownership to.
*/
function transferAdmin(address newAdmin) public onlyAdmin {
require(newAdmin != address(0));
TransferAdminPending(pendingAdmin);
pendingAdmin = newAdmin;
}
/**
* @dev Allows the current admin to set the admin in one tx. Useful initial deployment.
* @param newAdmin The address to transfer ownership to.
*/
function transferAdminQuickly(address newAdmin) public onlyAdmin {
require(newAdmin != address(0));
TransferAdminPending(newAdmin);
AdminClaimed(newAdmin, admin);
admin = newAdmin;
}
event AdminClaimed( address newAdmin, address previousAdmin);
/**
* @dev Allows the pendingAdmin address to finalize the change admin process.
*/
function claimAdmin() public {
require(pendingAdmin == msg.sender);
AdminClaimed(pendingAdmin, admin);
admin = pendingAdmin;
pendingAdmin = address(0);
}
event AlerterAdded (address newAlerter, bool isAdd);
function addAlerter(address newAlerter) public onlyAdmin {
require(!alerters[newAlerter]); // prevent duplicates.
require(alertersGroup.length < MAX_GROUP_SIZE);
AlerterAdded(newAlerter, true);
alerters[newAlerter] = true;
alertersGroup.push(newAlerter);
}
function removeAlerter (address alerter) public onlyAdmin {
require(alerters[alerter]);
alerters[alerter] = false;
for (uint i = 0; i < alertersGroup.length; ++i) {
if (alertersGroup[i] == alerter) {
alertersGroup[i] = alertersGroup[alertersGroup.length - 1];
alertersGroup.length--;
AlerterAdded(alerter, false);
break;
}
}
}
event OperatorAdded(address newOperator, bool isAdd);
function addOperator(address newOperator) public onlyAdmin {
require(!operators[newOperator]); // prevent duplicates.
require(operatorsGroup.length < MAX_GROUP_SIZE);
OperatorAdded(newOperator, true);
operators[newOperator] = true;
operatorsGroup.push(newOperator);
}
function removeOperator (address operator) public onlyAdmin {
require(operators[operator]);
operators[operator] = false;
for (uint i = 0; i < operatorsGroup.length; ++i) {
if (operatorsGroup[i] == operator) {
operatorsGroup[i] = operatorsGroup[operatorsGroup.length - 1];
operatorsGroup.length -= 1;
OperatorAdded(operator, false);
break;
}
}
}
}
contract Withdrawable is PermissionGroups {
event TokenWithdraw(ERC20 token, uint amount, address sendTo);
/**
* @dev Withdraw all ERC20 compatible tokens
* @param token ERC20 The address of the token contract
*/
function withdrawToken(ERC20 token, uint amount, address sendTo) external onlyAdmin {
require(token.transfer(sendTo, amount));
TokenWithdraw(token, amount, sendTo);
}
event EtherWithdraw(uint amount, address sendTo);
/**
* @dev Withdraw Ethers
*/
function withdrawEther(uint amount, address sendTo) external onlyAdmin {
sendTo.transfer(amount);
EtherWithdraw(amount, sendTo);
}
}
contract VolumeImbalanceRecorder is Withdrawable {
uint constant internal SLIDING_WINDOW_SIZE = 5;
uint constant internal POW_2_64 = 2 ** 64;
struct TokenControlInfo {
uint minimalRecordResolution; // can be roughly 1 cent
uint maxPerBlockImbalance; // in twei resolution
uint maxTotalImbalance; // max total imbalance (between rate updates)
// before halting trade
}
mapping(address => TokenControlInfo) internal tokenControlInfo;
struct TokenImbalanceData {
int lastBlockBuyUnitsImbalance;
uint lastBlock;
int totalBuyUnitsImbalance;
uint lastRateUpdateBlock;
}
mapping(address => mapping(uint=>uint)) public tokenImbalanceData;
function VolumeImbalanceRecorder(address _admin) public {
require(_admin != address(0));
admin = _admin;
}
function setTokenControlInfo(
ERC20 token,
uint minimalRecordResolution,
uint maxPerBlockImbalance,
uint maxTotalImbalance
)
public
onlyAdmin
{
tokenControlInfo[token] =
TokenControlInfo(
minimalRecordResolution,
maxPerBlockImbalance,
maxTotalImbalance
);
}
function getTokenControlInfo(ERC20 token) public view returns(uint, uint, uint) {
return (tokenControlInfo[token].minimalRecordResolution,
tokenControlInfo[token].maxPerBlockImbalance,
tokenControlInfo[token].maxTotalImbalance);
}
function addImbalance(
ERC20 token,
int buyAmount,
uint rateUpdateBlock,
uint currentBlock
)
internal
{
uint currentBlockIndex = currentBlock % SLIDING_WINDOW_SIZE;
int recordedBuyAmount = int(buyAmount / int(tokenControlInfo[token].minimalRecordResolution));
int prevImbalance = 0;
TokenImbalanceData memory currentBlockData =
decodeTokenImbalanceData(tokenImbalanceData[token][currentBlockIndex]);
// first scenario - this is not the first tx in the current block
if (currentBlockData.lastBlock == currentBlock) {
if (uint(currentBlockData.lastRateUpdateBlock) == rateUpdateBlock) {
// just increase imbalance
currentBlockData.lastBlockBuyUnitsImbalance += recordedBuyAmount;
currentBlockData.totalBuyUnitsImbalance += recordedBuyAmount;
} else {
// imbalance was changed in the middle of the block
prevImbalance = getImbalanceInRange(token, rateUpdateBlock, currentBlock);
currentBlockData.totalBuyUnitsImbalance = int(prevImbalance) + recordedBuyAmount;
currentBlockData.lastBlockBuyUnitsImbalance += recordedBuyAmount;
currentBlockData.lastRateUpdateBlock = uint(rateUpdateBlock);
}
} else {
// first tx in the current block
int currentBlockImbalance;
(prevImbalance, currentBlockImbalance) = getImbalanceSinceRateUpdate(token, rateUpdateBlock, currentBlock);
currentBlockData.lastBlockBuyUnitsImbalance = recordedBuyAmount;
currentBlockData.lastBlock = uint(currentBlock);
currentBlockData.lastRateUpdateBlock = uint(rateUpdateBlock);
currentBlockData.totalBuyUnitsImbalance = int(prevImbalance) + recordedBuyAmount;
}
tokenImbalanceData[token][currentBlockIndex] = encodeTokenImbalanceData(currentBlockData);
}
function setGarbageToVolumeRecorder(ERC20 token) internal {
for (uint i = 0; i < SLIDING_WINDOW_SIZE; i++) {
tokenImbalanceData[token][i] = 0x1;
}
}
function getImbalanceInRange(ERC20 token, uint startBlock, uint endBlock) internal view returns(int buyImbalance) {
// check the imbalance in the sliding window
require(startBlock <= endBlock);
buyImbalance = 0;
for (uint windowInd = 0; windowInd < SLIDING_WINDOW_SIZE; windowInd++) {
TokenImbalanceData memory perBlockData = decodeTokenImbalanceData(tokenImbalanceData[token][windowInd]);
if (perBlockData.lastBlock <= endBlock && perBlockData.lastBlock >= startBlock) {
buyImbalance += int(perBlockData.lastBlockBuyUnitsImbalance);
}
}
}
function getImbalanceSinceRateUpdate(ERC20 token, uint rateUpdateBlock, uint currentBlock)
internal view
returns(int buyImbalance, int currentBlockImbalance)
{
buyImbalance = 0;
currentBlockImbalance = 0;
uint latestBlock = 0;
int imbalanceInRange = 0;
uint startBlock = rateUpdateBlock;
uint endBlock = currentBlock;
for (uint windowInd = 0; windowInd < SLIDING_WINDOW_SIZE; windowInd++) {
TokenImbalanceData memory perBlockData = decodeTokenImbalanceData(tokenImbalanceData[token][windowInd]);
if (perBlockData.lastBlock <= endBlock && perBlockData.lastBlock >= startBlock) {
imbalanceInRange += perBlockData.lastBlockBuyUnitsImbalance;
}
if (perBlockData.lastRateUpdateBlock != rateUpdateBlock) continue;
if (perBlockData.lastBlock < latestBlock) continue;
latestBlock = perBlockData.lastBlock;
buyImbalance = perBlockData.totalBuyUnitsImbalance;
if (uint(perBlockData.lastBlock) == currentBlock) {
currentBlockImbalance = perBlockData.lastBlockBuyUnitsImbalance;
}
}
if (buyImbalance == 0) {
buyImbalance = imbalanceInRange;
}
}
function getImbalance(ERC20 token, uint rateUpdateBlock, uint currentBlock)
internal view
returns(int totalImbalance, int currentBlockImbalance)
{
int resolution = int(tokenControlInfo[token].minimalRecordResolution);
(totalImbalance, currentBlockImbalance) =
getImbalanceSinceRateUpdate(
token,
rateUpdateBlock,
currentBlock);
totalImbalance *= resolution;
currentBlockImbalance *= resolution;
}
function getMaxPerBlockImbalance(ERC20 token) internal view returns(uint) {
return tokenControlInfo[token].maxPerBlockImbalance;
}
function getMaxTotalImbalance(ERC20 token) internal view returns(uint) {
return tokenControlInfo[token].maxTotalImbalance;
}
function encodeTokenImbalanceData(TokenImbalanceData data) internal pure returns(uint) {
// check for overflows
require(data.lastBlockBuyUnitsImbalance < int(POW_2_64 / 2));
require(data.lastBlockBuyUnitsImbalance > int(-1 * int(POW_2_64) / 2));
require(data.lastBlock < POW_2_64);
require(data.totalBuyUnitsImbalance < int(POW_2_64 / 2));
require(data.totalBuyUnitsImbalance > int(-1 * int(POW_2_64) / 2));
require(data.lastRateUpdateBlock < POW_2_64);
// do encoding
uint result = uint(data.lastBlockBuyUnitsImbalance) & (POW_2_64 - 1);
result |= data.lastBlock * POW_2_64;
result |= (uint(data.totalBuyUnitsImbalance) & (POW_2_64 - 1)) * POW_2_64 * POW_2_64;
result |= data.lastRateUpdateBlock * POW_2_64 * POW_2_64 * POW_2_64;
return result;
}
function decodeTokenImbalanceData(uint input) internal pure returns(TokenImbalanceData) {
TokenImbalanceData memory data;
data.lastBlockBuyUnitsImbalance = int(int64(input & (POW_2_64 - 1)));
data.lastBlock = uint(uint64((input / POW_2_64) & (POW_2_64 - 1)));
data.totalBuyUnitsImbalance = int(int64((input / (POW_2_64 * POW_2_64)) & (POW_2_64 - 1)));
data.lastRateUpdateBlock = uint(uint64((input / (POW_2_64 * POW_2_64 * POW_2_64))));
return data;
}
}
contract Utils {
ERC20 constant internal ETH_TOKEN_ADDRESS = ERC20(0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee);
uint constant internal PRECISION = (10**18);
uint constant internal MAX_QTY = (10**28); // 10B tokens
uint constant internal MAX_RATE = (PRECISION * 10**6); // up to 1M tokens per ETH
uint constant internal MAX_DECIMALS = 18;
uint constant internal ETH_DECIMALS = 18;
mapping(address=>uint) internal decimals;
function setDecimals(ERC20 token) internal {
if (token == ETH_TOKEN_ADDRESS) decimals[token] = ETH_DECIMALS;
else decimals[token] = token.decimals();
}
function getDecimals(ERC20 token) internal view returns(uint) {
if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS; // save storage access
uint tokenDecimals = decimals[token];
// technically, there might be token with decimals 0
// moreover, very possible that old tokens have decimals 0
// these tokens will just have higher gas fees.
if(tokenDecimals == 0) return token.decimals();
return tokenDecimals;
}
function calcDstQty(uint srcQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns(uint) {
require(srcQty <= MAX_QTY);
require(rate <= MAX_RATE);
if (dstDecimals >= srcDecimals) {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS);
return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION;
} else {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS);
return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals)));
}
}
function calcSrcQty(uint dstQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns(uint) {
require(dstQty <= MAX_QTY);
require(rate <= MAX_RATE);
//source quantity is rounded up. to avoid dest quantity being too low.
uint numerator;
uint denominator;
if (srcDecimals >= dstDecimals) {
require((srcDecimals - dstDecimals) <= MAX_DECIMALS);
numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals)));
denominator = rate;
} else {
require((dstDecimals - srcDecimals) <= MAX_DECIMALS);
numerator = (PRECISION * dstQty);
denominator = (rate * (10**(dstDecimals - srcDecimals)));
}
return (numerator + denominator - 1) / denominator; //avoid rounding down errors
}
}
contract ConversionRates is ConversionRatesInterface, VolumeImbalanceRecorder, Utils {
// bps - basic rate steps. one step is 1 / 10000 of the rate.
struct StepFunction {
int[] x; // quantity for each step. Quantity of each step includes previous steps.
int[] y; // rate change per quantity step in bps.
}
struct TokenData {
bool listed; // was added to reserve
bool enabled; // whether trade is enabled
// position in the compact data
uint compactDataArrayIndex;
uint compactDataFieldIndex;
// rate data. base and changes according to quantity and reserve balance.
// generally speaking. Sell rate is 1 / buy rate i.e. the buy in the other direction.
uint baseBuyRate; // in PRECISION units. see KyberConstants
uint baseSellRate; // PRECISION units. without (sell / buy) spread it is 1 / baseBuyRate
StepFunction buyRateQtyStepFunction; // in bps. higher quantity - bigger the rate.
StepFunction sellRateQtyStepFunction;// in bps. higher the qua
StepFunction buyRateImbalanceStepFunction; // in BPS. higher reserve imbalance - bigger the rate.
StepFunction sellRateImbalanceStepFunction;
}
/*
this is the data for tokenRatesCompactData
but solidity compiler optimizer is sub-optimal, and cannot write this structure in a single storage write
so we represent it as bytes32 and do the byte tricks ourselves.
struct TokenRatesCompactData {
bytes14 buy; // change buy rate of token from baseBuyRate in 10 bps
bytes14 sell; // change sell rate of token from baseSellRate in 10 bps
uint32 blockNumber;
} */
uint public validRateDurationInBlocks = 10; // rates are valid for this amount of blocks
ERC20[] internal listedTokens;
mapping(address=>TokenData) internal tokenData;
bytes32[] internal tokenRatesCompactData;
uint public numTokensInCurrentCompactData = 0;
address public reserveContract;
uint constant internal NUM_TOKENS_IN_COMPACT_DATA = 14;
uint constant internal BYTES_14_OFFSET = (2 ** (8 * NUM_TOKENS_IN_COMPACT_DATA));
uint constant internal MAX_STEPS_IN_FUNCTION = 10;
int constant internal MAX_BPS_ADJUSTMENT = 10 ** 11; // 1B %
int constant internal MIN_BPS_ADJUSTMENT = -100 * 100; // cannot go down by more than 100%
function ConversionRates(address _admin) public VolumeImbalanceRecorder(_admin)
{ } // solhint-disable-line no-empty-blocks
function addToken(ERC20 token) public onlyAdmin {
require(!tokenData[token].listed);
tokenData[token].listed = true;
listedTokens.push(token);
if (numTokensInCurrentCompactData == 0) {
tokenRatesCompactData.length++; // add new structure
}
tokenData[token].compactDataArrayIndex = tokenRatesCompactData.length - 1;
tokenData[token].compactDataFieldIndex = numTokensInCurrentCompactData;
numTokensInCurrentCompactData = (numTokensInCurrentCompactData + 1) % NUM_TOKENS_IN_COMPACT_DATA;
setGarbageToVolumeRecorder(token);
setDecimals(token);
}
function setCompactData(bytes14[] buy, bytes14[] sell, uint blockNumber, uint[] indices) public onlyOperator {
require(buy.length == sell.length);
require(indices.length == buy.length);
require(blockNumber <= 0xFFFFFFFF);
uint bytes14Offset = BYTES_14_OFFSET;
for (uint i = 0; i < indices.length; i++) {
require(indices[i] < tokenRatesCompactData.length);
uint data = uint(buy[i]) | uint(sell[i]) * bytes14Offset | (blockNumber * (bytes14Offset * bytes14Offset));
tokenRatesCompactData[indices[i]] = bytes32(data);
}
}
function setBaseRate(
ERC20[] tokens,
uint[] baseBuy,
uint[] baseSell,
bytes14[] buy,
bytes14[] sell,
uint blockNumber,
uint[] indices
)
public
onlyOperator
{
require(tokens.length == baseBuy.length);
require(tokens.length == baseSell.length);
require(sell.length == buy.length);
require(sell.length == indices.length);
for (uint ind = 0; ind < tokens.length; ind++) {
require(tokenData[tokens[ind]].listed);
tokenData[tokens[ind]].baseBuyRate = baseBuy[ind];
tokenData[tokens[ind]].baseSellRate = baseSell[ind];
}
setCompactData(buy, sell, blockNumber, indices);
}
function setQtyStepFunction(
ERC20 token,
int[] xBuy,
int[] yBuy,
int[] xSell,
int[] ySell
)
public
onlyOperator
{
require(xBuy.length == yBuy.length);
require(xSell.length == ySell.length);
require(xBuy.length <= MAX_STEPS_IN_FUNCTION);
require(xSell.length <= MAX_STEPS_IN_FUNCTION);
require(tokenData[token].listed);
tokenData[token].buyRateQtyStepFunction = StepFunction(xBuy, yBuy);
tokenData[token].sellRateQtyStepFunction = StepFunction(xSell, ySell);
}
function setImbalanceStepFunction(
ERC20 token,
int[] xBuy,
int[] yBuy,
int[] xSell,
int[] ySell
)
public
onlyOperator
{
require(xBuy.length == yBuy.length);
require(xSell.length == ySell.length);
require(xBuy.length <= MAX_STEPS_IN_FUNCTION);
require(xSell.length <= MAX_STEPS_IN_FUNCTION);
require(tokenData[token].listed);
tokenData[token].buyRateImbalanceStepFunction = StepFunction(xBuy, yBuy);
tokenData[token].sellRateImbalanceStepFunction = StepFunction(xSell, ySell);
}
function setValidRateDurationInBlocks(uint duration) public onlyAdmin {
validRateDurationInBlocks = duration;
}
function enableTokenTrade(ERC20 token) public onlyAdmin {
require(tokenData[token].listed);
require(tokenControlInfo[token].minimalRecordResolution != 0);
tokenData[token].enabled = true;
}
function disableTokenTrade(ERC20 token) public onlyAlerter {
require(tokenData[token].listed);
tokenData[token].enabled = false;
}
function setReserveAddress(address reserve) public onlyAdmin {
reserveContract = reserve;
}
function recordImbalance(
ERC20 token,
int buyAmount,
uint rateUpdateBlock,
uint currentBlock
)
public
{
require(msg.sender == reserveContract);
if (rateUpdateBlock == 0) rateUpdateBlock = getRateUpdateBlock(token);
return addImbalance(token, buyAmount, rateUpdateBlock, currentBlock);
}
/* solhint-disable function-max-lines */
function getRate(ERC20 token, uint currentBlockNumber, bool buy, uint qty) public view returns(uint) {
// check if trade is enabled
if (!tokenData[token].enabled) return 0;
if (tokenControlInfo[token].minimalRecordResolution == 0) return 0; // token control info not set
// get rate update block
bytes32 compactData = tokenRatesCompactData[tokenData[token].compactDataArrayIndex];
uint updateRateBlock = getLast4Bytes(compactData);
if (currentBlockNumber >= updateRateBlock + validRateDurationInBlocks) return 0; // rate is expired
// check imbalance
int totalImbalance;
int blockImbalance;
(totalImbalance, blockImbalance) = getImbalance(token, updateRateBlock, currentBlockNumber);
// calculate actual rate
int imbalanceQty;
int extraBps;
int8 rateUpdate;
uint rate;
if (buy) {
// start with base rate
rate = tokenData[token].baseBuyRate;
// add rate update
rateUpdate = getRateByteFromCompactData(compactData, token, true);
extraBps = int(rateUpdate) * 10;
rate = addBps(rate, extraBps);
// compute token qty
qty = getTokenQty(token, rate, qty);
imbalanceQty = int(qty);
totalImbalance += imbalanceQty;
// add qty overhead
extraBps = executeStepFunction(tokenData[token].buyRateQtyStepFunction, int(qty));
rate = addBps(rate, extraBps);
// add imbalance overhead
extraBps = executeStepFunction(tokenData[token].buyRateImbalanceStepFunction, totalImbalance);
rate = addBps(rate, extraBps);
} else {
// start with base rate
rate = tokenData[token].baseSellRate;
// add rate update
rateUpdate = getRateByteFromCompactData(compactData, token, false);
extraBps = int(rateUpdate) * 10;
rate = addBps(rate, extraBps);
// compute token qty
imbalanceQty = -1 * int(qty);
totalImbalance += imbalanceQty;
// add qty overhead
extraBps = executeStepFunction(tokenData[token].sellRateQtyStepFunction, int(qty));
rate = addBps(rate, extraBps);
// add imbalance overhead
extraBps = executeStepFunction(tokenData[token].sellRateImbalanceStepFunction, totalImbalance);
rate = addBps(rate, extraBps);
}
if (abs(totalImbalance) >= getMaxTotalImbalance(token)) return 0;
if (abs(blockImbalance + imbalanceQty) >= getMaxPerBlockImbalance(token)) return 0;
return rate;
}
/* solhint-enable function-max-lines */
function getBasicRate(ERC20 token, bool buy) public view returns(uint) {
if (buy)
return tokenData[token].baseBuyRate;
else
return tokenData[token].baseSellRate;
}
function getCompactData(ERC20 token) public view returns(uint, uint, byte, byte) {
require(tokenData[token].listed);
uint arrayIndex = tokenData[token].compactDataArrayIndex;
uint fieldOffset = tokenData[token].compactDataFieldIndex;
return (
arrayIndex,
fieldOffset,
byte(getRateByteFromCompactData(tokenRatesCompactData[arrayIndex], token, true)),
byte(getRateByteFromCompactData(tokenRatesCompactData[arrayIndex], token, false))
);
}
function getTokenBasicData(ERC20 token) public view returns(bool, bool) {
return (tokenData[token].listed, tokenData[token].enabled);
}
/* solhint-disable code-complexity */
function getStepFunctionData(ERC20 token, uint command, uint param) public view returns(int) {
if (command == 0) return int(tokenData[token].buyRateQtyStepFunction.x.length);
if (command == 1) return tokenData[token].buyRateQtyStepFunction.x[param];
if (command == 2) return int(tokenData[token].buyRateQtyStepFunction.y.length);
if (command == 3) return tokenData[token].buyRateQtyStepFunction.y[param];
if (command == 4) return int(tokenData[token].sellRateQtyStepFunction.x.length);
if (command == 5) return tokenData[token].sellRateQtyStepFunction.x[param];
if (command == 6) return int(tokenData[token].sellRateQtyStepFunction.y.length);
if (command == 7) return tokenData[token].sellRateQtyStepFunction.y[param];
if (command == 8) return int(tokenData[token].buyRateImbalanceStepFunction.x.length);
if (command == 9) return tokenData[token].buyRateImbalanceStepFunction.x[param];
if (command == 10) return int(tokenData[token].buyRateImbalanceStepFunction.y.length);
if (command == 11) return tokenData[token].buyRateImbalanceStepFunction.y[param];
if (command == 12) return int(tokenData[token].sellRateImbalanceStepFunction.x.length);
if (command == 13) return tokenData[token].sellRateImbalanceStepFunction.x[param];
if (command == 14) return int(tokenData[token].sellRateImbalanceStepFunction.y.length);
if (command == 15) return tokenData[token].sellRateImbalanceStepFunction.y[param];
revert();
}
/* solhint-enable code-complexity */
function getRateUpdateBlock(ERC20 token) public view returns(uint) {
bytes32 compactData = tokenRatesCompactData[tokenData[token].compactDataArrayIndex];
return getLast4Bytes(compactData);
}
function getListedTokens() public view returns(ERC20[]) {
return listedTokens;
}
function getTokenQty(ERC20 token, uint ethQty, uint rate) internal view returns(uint) {
uint dstDecimals = getDecimals(token);
uint srcDecimals = ETH_DECIMALS;
return calcDstQty(ethQty, srcDecimals, dstDecimals, rate);
}
function getLast4Bytes(bytes32 b) internal pure returns(uint) {
// cannot trust compiler with not turning bit operations into EXP opcode
return uint(b) / (BYTES_14_OFFSET * BYTES_14_OFFSET);
}
function getRateByteFromCompactData(bytes32 data, ERC20 token, bool buy) internal view returns(int8) {
uint fieldOffset = tokenData[token].compactDataFieldIndex;
uint byteOffset;
if (buy)
byteOffset = 32 - NUM_TOKENS_IN_COMPACT_DATA + fieldOffset;
else
byteOffset = 4 + fieldOffset;
return int8(data[byteOffset]);
}
function executeStepFunction(StepFunction f, int x) internal pure returns(int) {
uint len = f.y.length;
for (uint ind = 0; ind < len; ind++) {
if (x <= f.x[ind]) return f.y[ind];
}
return f.y[len-1];
}
function addBps(uint rate, int bps) internal pure returns(uint) {
require(rate <= MAX_RATE);
require(bps >= MIN_BPS_ADJUSTMENT);
require(bps <= MAX_BPS_ADJUSTMENT);
uint maxBps = 100 * 100;
return (rate * uint(int(maxBps) + bps)) / maxBps;
}
function abs(int x) internal pure returns(uint) {
if (x < 0)
return uint(-1 * x);
else
return uint(x);
}
}
Read Contract
admin 0xf851a440 → address
getAlerters 0x7c423f54 → address[]
getBasicRate 0xcf8fee11 → uint256
getCompactData 0xe4a2ac62 → uint256, uint256, bytes1, bytes1
getListedTokens 0x2ba996a5 → address[]
getOperators 0x27a099d8 → address[]
getRate 0xb8e9c22e → uint256
getRateUpdateBlock 0x8036d757 → uint256
getStepFunctionData 0x62674e93 → int256
getTokenBasicData 0x721bba59 → bool, bool
getTokenControlInfo 0xe7d4fd91 → uint256, uint256, uint256
numTokensInCurrentCompactData 0x5085c9f1 → uint256
pendingAdmin 0x26782247 → address
reserveContract 0xa7f43acd → address
tokenImbalanceData 0xa80c609e → uint256
validRateDurationInBlocks 0x16265694 → uint256
Write Contract 20 functions
These functions modify contract state and require a wallet transaction to execute.
addAlerter 0x408ee7fe
address newAlerter
addOperator 0x9870d7fe
address newOperator
addToken 0xd48bfca7
address token
claimAdmin 0x77f50f97
No parameters
disableTokenTrade 0x158859f7
address token
enableTokenTrade 0x1d6a8bda
address token
recordImbalance 0xc6fd2103
address token
int256 buyAmount
uint256 rateUpdateBlock
uint256 currentBlock
removeAlerter 0x01a12fd3
address alerter
removeOperator 0xac8a584a
address operator
setBaseRate 0x1a4813d7
address[] tokens
uint256[] baseBuy
uint256[] baseSell
bytes14[] buy
bytes14[] sell
uint256 blockNumber
uint256[] indices
setCompactData 0x64887334
bytes14[] buy
bytes14[] sell
uint256 blockNumber
uint256[] indices
setImbalanceStepFunction 0xbc9cbcc8
address token
int256[] xBuy
int256[] yBuy
int256[] xSell
int256[] ySell
setQtyStepFunction 0x80d8b380
address token
int256[] xBuy
int256[] yBuy
int256[] xSell
int256[] ySell
setReserveAddress 0x14673d31
address reserve
setTokenControlInfo 0xbfee3569
address token
uint256 minimalRecordResolution
uint256 maxPerBlockImbalance
uint256 maxTotalImbalance
setValidRateDurationInBlocks 0x6c6295b8
uint256 duration
transferAdmin 0x75829def
address newAdmin
transferAdminQuickly 0x7acc8678
address newAdmin
withdrawEther 0xce56c454
uint256 amount
address sendTo
withdrawToken 0x3ccdbb28
address token
uint256 amount
address sendTo
Recent Transactions
This address has 1 on-chain transactions, but only 0.9% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →