Address Contract Partially Verified
Address
0x2172dF17543bC9400aE42ED24c2efE2B840e03f4
Balance
0 ETH
Nonce
1
Code Size
15937 bytes
Creator
0x0A33a70A...9Acc at tx 0x3d6f2ee0...c6455a
Indexed Transactions
Index loading...
Contract Bytecode
15937 bytes
0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806388d695b211610104578063cf6e4488116100a2578063e596219511610071578063e596219514610842578063ea5fbfd514610868578063eb55b2a31461088e578063f602c3121461093a576101da565b8063cf6e4488146107b9578063dd62ed3e146107d6578063de5007ff14610804578063dfe0f0ca1461080c576101da565b80639dc29fac116100de5780639dc29fac146105a9578063b7279ca6146105d5578063be23d29114610785578063cb81fecf146107b1576101da565b806388d695b21461044857806389064fd21461056b5780639189a59e146105a1576101da565b8063375b74c31161017c5780635d5e22cd1161014b5780635d5e22cd146103a857806361e1077d146103e457806370a082311461041a5780637f555b0314610440576101da565b8063375b74c31461032b578063380ba30c1461034f5780633a8343ee1461036e57806342966c681461038b576101da565b806318160ddd116101b857806318160ddd146102915780631c8e1179146102995780632e0179b5146102bf57806333bebb77146102f5576101da565b806304ff7d3f146101df578063053e89d71461021f57806315b2108214610259575b600080fd5b6101fc600480360360208110156101f557600080fd5b5035610942565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6102456004803603602081101561023557600080fd5b50356001600160a01b0316610967565b604080519115158252519081900360200190f35b61027f6004803603602081101561026f57600080fd5b50356001600160a01b03166109e3565b60408051918252519081900360200190f35b61027f610ab9565b610245600480360360208110156102af57600080fd5b50356001600160a01b0316610b3a565b610245600480360360608110156102d557600080fd5b506001600160a01b03813581169160208101359091169060400135610bb2565b6102456004803603606081101561030b57600080fd5b506001600160a01b03813581169160208101359091169060400135610efa565b6103336112e8565b604080516001600160a01b039092168252519081900360200190f35b61036c6004803603602081101561036557600080fd5b50356112f7565b005b61036c6004803603602081101561038457600080fd5b50356115e3565b610245600480360360208110156103a157600080fd5b50356116b0565b610245600480360360808110156103be57600080fd5b506001600160a01b0381358116916020810135821691604082013516906060013561197c565b610245600480360360608110156103fa57600080fd5b506001600160a01b03813581169160208101359091169060400135611ee9565b61027f6004803603602081101561043057600080fd5b50356001600160a01b0316612137565b6103336121bc565b6102456004803603604081101561045e57600080fd5b810190602081018135600160201b81111561047857600080fd5b82018360208201111561048a57600080fd5b803590602001918460208302840111600160201b831117156104ab57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156104fa57600080fd5b82018360208201111561050c57600080fd5b803590602001918460208302840111600160201b8311171561052d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506121cb945050505050565b6102456004803603606081101561058157600080fd5b506001600160a01b038135811691602081013590911690604001356125c8565b610333612843565b610245600480360360408110156105bf57600080fd5b506001600160a01b038135169060200135612852565b61036c600480360360808110156105eb57600080fd5b810190602081018135600160201b81111561060557600080fd5b82018360208201111561061757600080fd5b803590602001918460208302840111600160201b8311171561063857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561068757600080fd5b82018360208201111561069957600080fd5b803590602001918460208302840111600160201b831117156106ba57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561070957600080fd5b82018360208201111561071b57600080fd5b803590602001918460208302840111600160201b8311171561073c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b03169150612d3f9050565b61027f6004803603604081101561079b57600080fd5b506001600160a01b038135169060200135613214565b61027f6133de565b610333600480360360208110156107cf57600080fd5b50356133e4565b61027f600480360360408110156107ec57600080fd5b506001600160a01b03813581169160200135166133ff565b61027f61348d565b6102456004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135613493565b6102456004803603602081101561085857600080fd5b50356001600160a01b0316613815565b6102456004803603602081101561087e57600080fd5b50356001600160a01b031661382a565b61036c600480360360408110156108a457600080fd5b810190602081018135600160201b8111156108be57600080fd5b8201836020820111156108d057600080fd5b803590602001918460208302840111600160201b831117156108f157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b0316915061383f9050565b610333613c09565b600860205260009081526040902080546001909101546001600160a01b039091169082565b6001546000906001600160a01b031633146109ba576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b506001600160a01b03166000908152600960205260409020805460ff1916600190811790915590565b60006001600160a01b038216610a2a5760405162461bcd60e51b8152600401808060200182810382526026815260200180613d3a6026913960400191505060405180910390fd5b610a32613c18565b60408051602080820183526001600160a01b038087168084526000868152600284528590209351845492166001600160a01b031990921691909117909255825184815233918101919091528083019190915290519192507fd76fc900a7e1a6fcf11d54b7ba943918df6c53a3128140658c389b3da1e997ba919081900360600190a1919050565b6000600460009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0957600080fd5b505afa158015610b1d573d6000803e3d6000fd5b505050506040513d6020811015610b3357600080fd5b5051905090565b6001546000906001600160a01b03163314610b8d576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b506001600160a01b03166000908152600960205260409020805460ff19169055600190565b6003546000906001600160a01b03163314610c06576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920455243323050726f787960881b604482015290519081900360640190fd5b6001600160a01b038316610c61576040805162461bcd60e51b815260206004820152601960248201527f6e6f206e756c6c2076616c756520666f725f7370656e64657200000000000000604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16151560011415610cc2576040805162461bcd60e51b815260206004820152601b6024820152600080516020613cf5833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff16151560011415610d35576040805162461bcd60e51b815260206004820152601c60248201527f5f7370656e646572206d757374206e6f7420626520626c6f636b656400000000604482015290519081900360640190fd5b6004805460408051635c65816560e01b81526001600160a01b03888116948201949094528684166024820152905160009390921691635c65816591604480820192602092909190829003018186803b158015610d9057600080fd5b505afa158015610da4573d6000803e3d6000fd5b505050506040513d6020811015610dba57600080fd5b5051905082810181811015610e005760405162461bcd60e51b815260040180806020018281038252602f815260200180613cc6602f913960400191505060405180910390fd5b6004805460408051633691826360e21b81526001600160a01b038a8116948201949094528884166024820152604481018590529051929091169163da46098c9160648082019260009290919082900301818387803b158015610e6157600080fd5b505af1158015610e75573d6000803e3d6000fd5b505060035460408051630ad0fe5760e31b81526001600160a01b038b811660048301528a81166024830152604482018790529151919092169350635687f2b89250606480830192600092919082900301818387803b158015610ed657600080fd5b505af1158015610eea573d6000803e3d6000fd5b5060019998505050505050505050565b6001546000906001600160a01b03163314610f4d576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b6001600160a01b038316610fa2576040805162461bcd60e51b81526020600482015260176024820152760373790373ab636103b30b63ab2903337b910302fba37b604d1b604482015290519081900360640190fd5b60048054604080516327e235e360e01b81526001600160a01b03888116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b158015610ff557600080fd5b505afa158015611009573d6000803e3d6000fd5b505050506040513d602081101561101f57600080fd5b505190508083116111875760048054604080516338c110ef60e21b81526001600160a01b038981169482019490945286850360248201529051929091169163e30443bc9160448082019260009290919082900301818387803b15801561108457600080fd5b505af1158015611098573d6000803e3d6000fd5b505060048054604080516310f29c1d60e11b81526001600160a01b038a8116948201949094526024810189905290519290911693506321e5383a925060448082019260009290919082900301818387803b1580156110f557600080fd5b505af1158015611109573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038a8116600483015289811660248301526044820189905291519190921693506323de66519250606480830192600092919082900301818387803b15801561116a57600080fd5b505af115801561117e573d6000803e3d6000fd5b505050506112dd565b60048054604080516338c110ef60e21b81526001600160a01b03898116948201949094526000602482018190529151939092169263e30443bc92604480820193929182900301818387803b1580156111de57600080fd5b505af11580156111f2573d6000803e3d6000fd5b505060048054604080516310f29c1d60e11b81526001600160a01b038a8116948201949094526024810187905290519290911693506321e5383a925060448082019260009290919082900301818387803b15801561124f57600080fd5b505af1158015611263573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038a8116600483015289811660248301526044820187905291519190921693506323de66519250606480830192600092919082900301818387803b1580156112c457600080fd5b505af11580156112d8573d6000803e3d6000fd5b505050505b506001949350505050565b6001546001600160a01b031681565b6001546001600160a01b03163314611347576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b600081815260086020526040902080546001600160a01b0316806113a6576040805162461bcd60e51b815260206004820152601160248201527003ab735b737bbb710302fb637b1b5a4b23607d1b604482015290519081900360640190fd5b600182810154600085815260086020908152604080832080546001600160a01b03191681559094018290556004805485516318160ddd60e01b81529551949593946001600160a01b03909116936318160ddd9381840193909291829003018186803b15801561141457600080fd5b505afa158015611428573d6000803e3d6000fd5b505050506040513d602081101561143e57600080fd5b505190508181018181106115db57600480546040805163f7ea7a3d60e01b8152928301849052516001600160a01b039091169163f7ea7a3d91602480830192600092919082900301818387803b15801561149757600080fd5b505af11580156114ab573d6000803e3d6000fd5b505060048054604080516310f29c1d60e11b81526001600160a01b038a8116948201949094526024810189905290519290911693506321e5383a925060448082019260009290919082900301818387803b15801561150857600080fd5b505af115801561151c573d6000803e3d6000fd5b5050604080518981526001600160a01b038816602082015280820187905290517f1445852a2ef41b86fd81f90a02261a68635ceb02cdbc73f9c5f690af8288f3609350908190036060019150a1600354604080516323de665160e01b81526000600482018190526001600160a01b03888116602484015260448301889052925192909316926323de66519260648084019382900301818387803b1580156115c257600080fd5b505af11580156115d6573d6000803e3d6000fd5b505050505b505050505050565b6001546001600160a01b03163314611633576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b61163c81613c61565b600180546001600160a01b039283166001600160a01b031991821617825560008481526002602090815260409182902080549093169092559154825185815293169083015280517f9a99272c0f6b7a30ef9e76e684a7cd408bfd4f11a72f36a8e276253c920e442d9281900390910190a150565b3360009081526009602052604081205460ff1615156001141561170c576040805162461bcd60e51b815260206004820152600f60248201526e1858d8dbdd5b9d08189b1bd8dad959608a1b604482015290519081900360640190fd5b60048054604080516327e235e360e01b81523393810193909352516000926001600160a01b03909216916327e235e3916024808301926020929190829003018186803b15801561175b57600080fd5b505afa15801561176f573d6000803e3d6000fd5b505050506040513d602081101561178557600080fd5b50519050808311156117c85760405162461bcd60e51b8152600401808060200182810382526031815260200180613d886031913960400191505060405180910390fd5b60048054604080516338c110ef60e21b815233938101939093528584036024840152516001600160a01b039091169163e30443bc91604480830192600092919082900301818387803b15801561181d57600080fd5b505af1158015611831573d6000803e3d6000fd5b505060048054604080516318160ddd60e01b815290516001600160a01b03909216945063f7ea7a3d9350879285926318160ddd928083019260209291829003018186803b15801561188157600080fd5b505afa158015611895573d6000803e3d6000fd5b505050506040513d60208110156118ab57600080fd5b5051604080516001600160e01b031960e086901b16815292909103600483015251602480830192600092919082900301818387803b1580156118ec57600080fd5b505af1158015611900573d6000803e3d6000fd5b5050600354604080516323de665160e01b81523360048201526000602482018190526044820189905291516001600160a01b0390931694506323de665193506064808201939182900301818387803b15801561195b57600080fd5b505af115801561196f573d6000803e3d6000fd5b5060019695505050505050565b6003546000906001600160a01b031633146119d0576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920455243323050726f787960881b604482015290519081900360640190fd5b6001600160a01b038316611a2b576040805162461bcd60e51b815260206004820152601860248201527f6e6f206e756c6c2076616c75657320666f7220605f746f600000000000000000604482015290519081900360640190fd5b6001600160a01b03851660009081526009602052604090205460ff16151560011415611a8c576040805162461bcd60e51b815260206004820152601b6024820152600080516020613cf5833981519152604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16151560011415611aff576040805162461bcd60e51b815260206004820152601960248201527f5f66726f6d206d757374206e6f7420626520626c6f636b656400000000000000604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff16151560011415611b6c576040805162461bcd60e51b815260206004820152601760248201527617dd1bc81b5d5cdd081b9bdd08189948189b1bd8dad959604a1b604482015290519081900360640190fd5b60048054604080516327e235e360e01b81526001600160a01b03888116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b158015611bbf57600080fd5b505afa158015611bd3573d6000803e3d6000fd5b505050506040513d6020811015611be957600080fd5b5051905080831115611c2c5760405162461bcd60e51b8152600401808060200182810382526025815260200180613d156025913960400191505060405180910390fd5b6004805460408051635c65816560e01b81526001600160a01b03898116948201949094528984166024820152905160009390921691635c65816591604480820192602092909190829003018186803b158015611c8757600080fd5b505afa158015611c9b573d6000803e3d6000fd5b505050506040513d6020811015611cb157600080fd5b5051905080841115611d0a576040805162461bcd60e51b815260206004820152601d60248201527f696e73756666696369656e7420616c6c6f77616e636520616d6f756e74000000604482015290519081900360640190fd5b60048054604080516338c110ef60e21b81526001600160a01b038a81169482019490945287860360248201529051929091169163e30443bc9160448082019260009290919082900301818387803b158015611d6457600080fd5b505af1158015611d78573d6000803e3d6000fd5b505060048054604080516310f29c1d60e11b81526001600160a01b038b811694820194909452602481018a905290519290911693506321e5383a925060448082019260009290919082900301818387803b158015611dd557600080fd5b505af1158015611de9573d6000803e3d6000fd5b50506004805460408051633691826360e21b81526001600160a01b038c8116948201949094528c841660248201528987036044820152905192909116935063da46098c925060648082019260009290919082900301818387803b158015611e4f57600080fd5b505af1158015611e63573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038b811660048301528a81166024830152604482018a905291519190921693506323de66519250606480830192600092919082900301818387803b158015611ec457600080fd5b505af1158015611ed8573d6000803e3d6000fd5b5060019a9950505050505050505050565b6003546000906001600160a01b03163314611f3d576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920455243323050726f787960881b604482015290519081900360640190fd5b6001600160a01b038316611f98576040805162461bcd60e51b815260206004820152601860248201527f6e6f20756e7370656e6461626c6520617070726f76616c730000000000000000604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff16151560011415611ff9576040805162461bcd60e51b815260206004820152601b6024820152600080516020613cf5833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff1615156001141561206c576040805162461bcd60e51b815260206004820152601c60248201527f5f7370656e646572206d757374206e6f7420626520626c6f636b656400000000604482015290519081900360640190fd5b6004805460408051635c65816560e01b81526001600160a01b03888116948201949094528684166024820152905160009390921691635c65816591604480820192602092909190829003018186803b1580156120c757600080fd5b505afa1580156120db573d6000803e3d6000fd5b505050506040513d60208110156120f157600080fd5b5051905082810381811115610e005760405162461bcd60e51b815260040180806020018281038252602f815260200180613cc6602f913960400191505060405180910390fd5b60048054604080516327e235e360e01b81526001600160a01b03858116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b15801561218a57600080fd5b505afa15801561219e573d6000803e3d6000fd5b505050506040513d60208110156121b457600080fd5b505192915050565b6003546001600160a01b031681565b6000815183511461220d5760405162461bcd60e51b8152600401808060200182810382526028815260200180613d606028913960400191505060405180910390fd5b3360009081526009602052604090205460ff16151560011415612269576040805162461bcd60e51b815260206004820152600f60248201526e1858d8dbdd5b9d08189b1bd8dad959608a1b604482015290519081900360640190fd5b825160048054604080516327e235e360e01b81523393810193909352516000926001600160a01b03909216916327e235e3916024808301926020929190829003018186803b1580156122ba57600080fd5b505afa1580156122ce573d6000803e3d6000fd5b505050506040513d60208110156122e457600080fd5b5051905060005b8281101561255057600086828151811061230157fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415612373576040805162461bcd60e51b815260206004820152601760248201527f6e6f206e756c6c2076616c75657320666f72205f746f73000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526009602052604090205460ff161515600114156123e6576040805162461bcd60e51b815260206004820152601860248201527f5f746f73206d757374206e6f7420626520626c6f636b65640000000000000000604482015290519081900360640190fd5b60008683815181106123f457fe5b6020026020010151905080841015612448576040805162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b604482015290519081900360640190fd5b336001600160a01b038316146124cf5760048054604080516310f29c1d60e11b81526001600160a01b0386811694820194909452602481018590529051968490039692909116916321e5383a9160448082019260009290919082900301818387803b1580156124b657600080fd5b505af11580156124ca573d6000803e3d6000fd5b505050505b600354604080516323de665160e01b81523360048201526001600160a01b03858116602483015260448201859052915191909216916323de665191606480830192600092919082900301818387803b15801561252a57600080fd5b505af115801561253e573d6000803e3d6000fd5b5050600190940193506122eb92505050565b5060048054604080516338c110ef60e21b8152339381019390935260248301849052516001600160a01b039091169163e30443bc91604480830192600092919082900301818387803b1580156125a557600080fd5b505af11580156125b9573d6000803e3d6000fd5b50600198975050505050505050565b6003546000906001600160a01b0316331461261c576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920455243323050726f787960881b604482015290519081900360640190fd5b6001600160a01b038316612677576040805162461bcd60e51b815260206004820152601c60248201527f6e6f206e756c6c2076616c756520666f7220605f7370656e6465726000000000604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff161515600114156126d8576040805162461bcd60e51b815260206004820152601b6024820152600080516020613cf5833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff1615156001141561274b576040805162461bcd60e51b815260206004820152601c60248201527f5f7370656e646572206d757374206e6f7420626520626c6f636b656400000000604482015290519081900360640190fd5b6004805460408051633691826360e21b81526001600160a01b03888116948201949094528684166024820152604481018690529051929091169163da46098c9160648082019260009290919082900301818387803b1580156127ac57600080fd5b505af11580156127c0573d6000803e3d6000fd5b505060035460408051630ad0fe5760e31b81526001600160a01b0389811660048301528881166024830152604482018890529151919092169350635687f2b89250606480830192600092919082900301818387803b15801561282157600080fd5b505af1158015612835573d6000803e3d6000fd5b506001979650505050505050565b6005546001600160a01b031681565b6001546000906001600160a01b031633146128a5576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9031bab9ba37b234b0b760911b604482015290519081900360640190fd5b60048054604080516327e235e360e01b81526001600160a01b03878116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b1580156128f857600080fd5b505afa15801561290c573d6000803e3d6000fd5b505050506040513d602081101561292257600080fd5b50519050808311612b355760048054604080516338c110ef60e21b81526001600160a01b038881169482019490945286850360248201529051929091169163e30443bc9160448082019260009290919082900301818387803b15801561298757600080fd5b505af115801561299b573d6000803e3d6000fd5b505060048054604080516318160ddd60e01b815290516001600160a01b03909216945063f7ea7a3d9350879285926318160ddd928083019260209291829003018186803b1580156129eb57600080fd5b505afa1580156129ff573d6000803e3d6000fd5b505050506040513d6020811015612a1557600080fd5b5051604080516001600160e01b031960e086901b16815292909103600483015251602480830192600092919082900301818387803b158015612a5657600080fd5b505af1158015612a6a573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038981166004830152600060248301819052604483018a90529251931694506323de665193506064808201939182900301818387803b158015612ac657600080fd5b505af1158015612ada573d6000803e3d6000fd5b5050604080516001600160a01b038816815260208101879052808201879052868503606082015290517fcad422cff53a884518c31f745fc74d67f0585184b33e4b9b602ce24277665ebf9350908190036080019150a1612d35565b60048054604080516338c110ef60e21b81526001600160a01b03888116948201949094526000602482018190529151939092169263e30443bc92604480820193929182900301818387803b158015612b8c57600080fd5b505af1158015612ba0573d6000803e3d6000fd5b505060048054604080516318160ddd60e01b815290516001600160a01b03909216945063f7ea7a3d9350859285926318160ddd928083019260209291829003018186803b158015612bf057600080fd5b505afa158015612c04573d6000803e3d6000fd5b505050506040513d6020811015612c1a57600080fd5b5051604080516001600160e01b031960e086901b16815292909103600483015251602480830192600092919082900301818387803b158015612c5b57600080fd5b505af1158015612c6f573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038981166004830152600060248301819052604483018890529251931694506323de665193506064808201939182900301818387803b158015612ccb57600080fd5b505af1158015612cdf573d6000803e3d6000fd5b5050604080516001600160a01b0388168152602081018790528082018590526000606082015290517fcad422cff53a884518c31f745fc74d67f0585184b33e4b9b602ce24277665ebf9350908190036080019150a15b5060019392505050565b6005546001600160a01b03163314612d8d576040805162461bcd60e51b815260206004820152600c60248201526b37b7363c9039bbb2b2b832b960a11b604482015290519081900360640190fd5b6001600160a01b038116612de2576040805162461bcd60e51b81526020600482015260176024820152760373790373ab636103b30b63ab2903337b910302fba37b604d1b604482015290519081900360640190fd5b6001600160a01b03811660009081526009602052604090205460ff16151560011415612e4f576040805162461bcd60e51b815260206004820152601760248201527617dd1bc81b5d5cdd081b9bdd08189948189b1bd8dad959604a1b604482015290519081900360640190fd5b82518451148015612e61575081518451145b612e9c5760405162461bcd60e51b8152600401808060200182810382526027815260200180613de66027913960400191505060405180910390fd5b83516000805b828110156131b4576000600160065460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182815260200191505060405160208183030381529060405280519060200120898481518110612f0b57fe5b6020026020010151898581518110612f1f57fe5b6020026020010151898681518110612f3357fe5b602002602001015160405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612f92573d6000803e3d6000fd5b505060408051601f1901516001600160a01b03811660009081526009602052919091205490925060ff161515600114159050613015576040805162461bcd60e51b815260206004820152601a60248201527f5f66726f6d73206d757374206e6f7420626520626c6f636b6564000000000000604482015290519081900360640190fd5b6001600160a01b038116156131ab576001600160a01b038082166000818152600760209081526040808320805460ff191660011790556004805482516327e235e360e01b8152918201959095529051929493909316926327e235e39260248083019392829003018186803b15801561308c57600080fd5b505afa1580156130a0573d6000803e3d6000fd5b505050506040513d60208110156130b657600080fd5b5051905080156131a95760048054604080516338c110ef60e21b81526001600160a01b0386811694820194909452600060248201819052915197850197939092169263e30443bc92604480820193929182900301818387803b15801561311b57600080fd5b505af115801561312f573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b0387811660048301528b811660248301526044820187905291519190921693506323de66519250606480830192600092919082900301818387803b15801561319057600080fd5b505af11580156131a4573d6000803e3d6000fd5b505050505b505b50600101612ea2565b5080156115db5760048054604080516310f29c1d60e11b81526001600160a01b038781169482019490945260248101859052905192909116916321e5383a9160448082019260009290919082900301818387803b1580156115c257600080fd5b60006001600160a01b038316613271576040805162461bcd60e51b815260206004820152601d60248201527f6e6f206e756c6c2076616c756520666f7220605f726563656976657260000000604482015290519081900360640190fd5b3360009081526009602052604090205460ff161515600114156132cd576040805162461bcd60e51b815260206004820152600f60248201526e1858d8dbdd5b9d08189b1bd8dad959608a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff16151560011415613340576040805162461bcd60e51b815260206004820152601d60248201527f5f7265636569766572206d757374206e6f7420626520626c6f636b6564000000604482015290519081900360640190fd5b613348613c18565b6040805180820182526001600160a01b0380871680835260208084018881526000878152600883528690209451855494166001600160a01b0319909416939093178455915160019093019290925582518481529081019190915280820185905290519192507f021724c3943709b5b29b9cdcfb21e18e7355b036e07d869b4a69bd8a13ec45e8919081900360600190a192915050565b60005481565b6002602052600090815260409020546001600160a01b031681565b6004805460408051635c65816560e01b81526001600160a01b03868116948201949094528484166024820152905160009390921691635c65816591604480820192602092909190829003018186803b15801561345a57600080fd5b505afa15801561346e573d6000803e3d6000fd5b505050506040513d602081101561348457600080fd5b50519392505050565b60065481565b6003546000906001600160a01b031633146134e7576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920455243323050726f787960881b604482015290519081900360640190fd5b6001600160a01b03831661353c576040805162461bcd60e51b81526020600482015260176024820152760373790373ab636103b30b63ab2903337b910302fba37b604d1b604482015290519081900360640190fd5b6001600160a01b03841660009081526009602052604090205460ff1615156001141561359d576040805162461bcd60e51b815260206004820152601b6024820152600080516020613cf5833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526009602052604090205460ff1615156001141561360a576040805162461bcd60e51b815260206004820152601760248201527617dd1bc81b5d5cdd081b9bdd08189948189b1bd8dad959604a1b604482015290519081900360640190fd5b60048054604080516327e235e360e01b81526001600160a01b03888116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b15801561365d57600080fd5b505afa158015613671573d6000803e3d6000fd5b505050506040513d602081101561368757600080fd5b50519050808311156136d5576040805162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b604482015290519081900360640190fd5b60048054604080516338c110ef60e21b81526001600160a01b038981169482019490945286850360248201529051929091169163e30443bc9160448082019260009290919082900301818387803b15801561372f57600080fd5b505af1158015613743573d6000803e3d6000fd5b505060048054604080516310f29c1d60e11b81526001600160a01b038a8116948201949094526024810189905290519290911693506321e5383a925060448082019260009290919082900301818387803b1580156137a057600080fd5b505af11580156137b4573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b038a8116600483015289811660248301526044820189905291519190921693506323de66519250606480830192600092919082900301818387803b1580156112c457600080fd5b60096020526000908152604090205460ff1681565b60076020526000908152604090205460ff1681565b6005546001600160a01b0316331461388d576040805162461bcd60e51b815260206004820152600c60248201526b37b7363c9039bbb2b2b832b960a11b604482015290519081900360640190fd5b6001600160a01b0381166138e2576040805162461bcd60e51b81526020600482015260176024820152760373790373ab636103b30b63ab2903337b910302fba37b604d1b604482015290519081900360640190fd5b6001600160a01b03811660009081526009602052604090205460ff1615156001141561394f576040805162461bcd60e51b815260206004820152601760248201527617dd1bc81b5d5cdd081b9bdd08189948189b1bd8dad959604a1b604482015290519081900360640190fd5b81516000805b82811015613b8a57600085828151811061396b57fe5b6020908102919091018101516001600160a01b0381166000908152600990925260409091205490915060ff161515600114156139ee576040805162461bcd60e51b815260206004820152601a60248201527f5f66726f6d73206d757374206e6f7420626520626c6f636b6564000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526007602052604090205460ff1615613b815760048054604080516327e235e360e01b81526001600160a01b03858116948201949094529051600093909216916327e235e391602480820192602092909190829003018186803b158015613a6257600080fd5b505afa158015613a76573d6000803e3d6000fd5b505050506040513d6020811015613a8c57600080fd5b505190508015613b7f5760048054604080516338c110ef60e21b81526001600160a01b0386811694820194909452600060248201819052915197850197939092169263e30443bc92604480820193929182900301818387803b158015613af157600080fd5b505af1158015613b05573d6000803e3d6000fd5b5050600354604080516323de665160e01b81526001600160a01b0387811660048301528b811660248301526044820187905291519190921693506323de66519250606480830192600092919082900301818387803b158015613b6657600080fd5b505af1158015613b7a573d6000803e3d6000fd5b505050505b505b50600101613955565b508015613c035760048054604080516310f29c1d60e11b81526001600160a01b038781169482019490945260248101859052905192909116916321e5383a9160448082019260009290919082900301818387803b158015613bea57600080fd5b505af1158015613bfe573d6000803e3d6000fd5b505050505b50505050565b6004546001600160a01b031681565b6000805460010190819055604080516000194301406020808301919091523060601b82840152605480830194909452825180830390940184526074909101909152815191012090565b600081815260026020526040812080546001600160a01b0316613cb55760405162461bcd60e51b815260040180806020018281038252602d815260200180613db9602d913960400191505060405180910390fd5b546001600160a01b03169291505056fe6e657720616c6c6f77616e6365206d757374206e6f7420626520736d616c6c6572207468616e2070726576696f75735f73656e646572206d757374206e6f7420626520626c6f636b65640000000000696e73756666696369656e742066756e6473206f6e20605f66726f6d602062616c616e63656e6f206e756c6c2076616c756520666f7220605f70726f706f736564437573746f6469616e605f746f7320616e64205f76616c756573206d757374206265207468652073616d65206c656e677468646973616c6c6f77206275726e696e67206d6f72652c207468616e20616d6f756e74206f66207468652062616c616e636572656a65637420e280986e756c6ce2809920726573756c74732066726f6d20746865206d6170206c6f6f6b75705f76735b5d2c205f72735b5d2c205f7373206c656e677468732061726520646966666572656e74a265627a7a723058200cb00a48fc732a064b1790adc62fc5f089c0165359c962b6c4a453d61e14a68064736f6c634300050a0032
Verified Source Code Partial Match
Compiler: v0.5.10+commit.5a6ea5b1
EVM: petersburg
Optimization: Yes (200 runs)
ERC20Impl.sol 1839 lines
pragma solidity ^0.5.10;
/** @title A contract for generating unique identifiers
*
* @notice A contract that provides an identifier generation scheme,
* guaranteeing uniqueness across all contracts that inherit from it,
* as well as the unpredictability of future identifiers.
*
* @dev This contract is intended to be inherited by any contract that
* implements the callback software pattern for cooperative custodianship.
*
*/
contract LockRequestable {
// MEMBERS
/// @notice the count of all invocations of `generateLockId`.
uint256 public lockRequestCount;
// CONSTRUCTOR
constructor() public {
lockRequestCount = 0;
}
// FUNCTIONS
/** @notice Returns a fresh unique identifier.
*
* @dev the generation scheme uses three components.
* First, the blockhash of the previous block.
* Second, the deployed address.
* Third, the next value of the counter.
* This ensures that identifiers are unique across all contracts
* following this scheme, and that future identifiers are
* unpredictable.
*
* @return a 32-byte unique identifier.
*/
function generateLockId() internal returns (bytes32 lockId) {
return keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), ++lockRequestCount));
}
}
contract ERC20Interface {
// METHODS
// NOTE:
// public getter functions are not currently recognised as an
// implementation of the matching abstract function by the compiler.
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#name
// function name() public view returns (string);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#symbol
// function symbol() public view returns (string);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#totalsupply
// function decimals() public view returns (uint8);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#totalsupply
function totalSupply() public view returns (uint256);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#balanceof
function balanceOf(address _owner) public view returns (uint256 balance);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer
function transfer(address _to, uint256 _value) public returns (bool success);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transferfrom
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approve
function approve(address _spender, uint256 _value) public returns (bool success);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#allowance
function allowance(address _owner, address _spender) public view returns (uint256 remaining);
// EVENTS
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer-1
event Transfer(address indexed _from, address indexed _to, uint256 _value);
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approval
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
/** @title A dual control contract.
*
* @notice A general-purpose contract that implements dual control over
* co-operating contracts through a callback mechanism.
*
* @dev This contract implements dual control through a 2-of-N
* threshold multi-signature scheme. The contract recognizes a set of N signers,
* and will unlock requests with signatures from any distinct pair of them.
* This contract signals the unlocking through a co-operative callback
* scheme.
* This contract also provides time lock and revocation features.
* Requests made by a 'primary' account have a default time lock applied.
* All other requests must pay a 1 ETH stake and have an extended time lock
* applied.
* A request that is completed will prevent all previous pending requests
* that share the same callback from being completed: this is the
* revocation feature.
*
*/
contract Custodian {
// TYPES
/** @dev The `Request` struct stores a pending unlocking.
* `callbackAddress` and `callbackSelector` are the data required to
* make a callback. The custodian completes the process by
* calling `callbackAddress.call(callbackSelector, lockId)`, which
* signals to the contract co-operating with the Custodian that
* the 2-of-N signatures have been provided and verified.
*/
struct Request {
bytes32 lockId;
bytes4 callbackSelector; // bytes4 and address can be packed into 1 word
address callbackAddress;
uint256 idx;
uint256 timestamp;
bool extended;
}
// EVENTS
/// @dev Emitted by successful `requestUnlock` calls.
event Requested(
bytes32 _lockId,
address _callbackAddress,
bytes4 _callbackSelector,
uint256 _nonce,
address _whitelistedAddress,
bytes32 _requestMsgHash,
uint256 _timeLockExpiry
);
/// @dev Emitted by `completeUnlock` calls on requests in the time-locked state.
event TimeLocked(
uint256 _timeLockExpiry,
bytes32 _requestMsgHash
);
/// @dev Emitted by successful `completeUnlock` calls.
event Completed(
bytes32 _lockId,
bytes32 _requestMsgHash,
address _signer1,
address _signer2
);
/// @dev Emitted by `completeUnlock` calls where the callback failed.
event Failed(
bytes32 _lockId,
bytes32 _requestMsgHash,
address _signer1,
address _signer2
);
/// @dev Emitted by successful `extendRequestTimeLock` calls.
event TimeLockExtended(
uint256 _timeLockExpiry,
bytes32 _requestMsgHash
);
// MEMBERS
/** @dev The count of all requests.
* This value is used as a nonce, incorporated into the request hash.
*/
uint256 public requestCount;
/// @dev The set of signers: signatures from two signers unlock a pending request.
mapping (address => bool) public signerSet;
/// @dev The map of request hashes to pending requests.
mapping (bytes32 => Request) public requestMap;
/// @dev The map of callback addresses to callback selectors to request indexes.
mapping (address => mapping (bytes4 => uint256)) public lastCompletedIdxs;
/** @dev The default period (in seconds) to time-lock requests.
* All requests will be subject to this default time lock, and the duration
* is fixed at contract creation.
*/
uint256 public defaultTimeLock;
/** @dev The extended period (in seconds) to time-lock requests.
* Requests not from the primary account are subject to this time lock.
* The primary account may also elect to extend the time lock on requests
* that originally received the default.
*/
uint256 public extendedTimeLock;
/// @dev The primary account is the privileged account for making requests.
address public primary;
// CONSTRUCTOR
constructor(
address[] memory _signers,
uint256 _defaultTimeLock,
uint256 _extendedTimeLock,
address _primary
)
public
{
// check for at least two `_signers`
require(_signers.length >= 2, "at least two `_signers`");
// validate time lock params
require(_defaultTimeLock <= _extendedTimeLock, "valid timelock params");
defaultTimeLock = _defaultTimeLock;
extendedTimeLock = _extendedTimeLock;
primary = _primary;
// explicitly initialize `requestCount` to zero
requestCount = 0;
// turn the array into a set
for (uint i = 0; i < _signers.length; i++) {
// no zero addresses or duplicates
require(_signers[i] != address(0) && !signerSet[_signers[i]], "no zero addresses or duplicates");
signerSet[_signers[i]] = true;
}
}
// MODIFIERS
modifier onlyPrimary {
require(msg.sender == primary, "only primary");
_;
}
modifier onlySigner {
require(signerSet[msg.sender], "only signer");
_;
}
// METHODS
/** @notice Requests an unlocking with a lock identifier and a callback.
*
* @dev If called by an account other than the primary a 1 ETH stake
* must be paid. When the request is unlocked stake will be transferred to the message sender.
* This is an anti-spam measure. As well as the callback
* and the lock identifier parameters a 'whitelisted address' is required
* for compatibility with existing signature schemes.
*
* @param _lockId The identifier of a pending request in a co-operating contract.
* @param _callbackAddress The address of a co-operating contract.
* @param _callbackSelector The function selector of a function within
* the co-operating contract at address `_callbackAddress`.
* @param _whitelistedAddress An address whitelisted in existing
* offline control protocols.
*
* @return requestMsgHash The hash of a request message to be signed.
*/
function requestUnlock(
bytes32 _lockId,
address _callbackAddress,
bytes4 _callbackSelector,
address _whitelistedAddress
)
public
payable
returns (bytes32 requestMsgHash)
{
require(msg.sender == primary || msg.value >= 1 ether, "sender is primary or stake is paid");
// disallow using a zero value for the callback address
require(_callbackAddress != address(0), "no zero value for callback address");
uint256 requestIdx = ++requestCount;
// compute a nonce value
// - the blockhash prevents prediction of future nonces
// - the address of this contract prevents conflicts with co-operating contracts using this scheme
// - the counter prevents conflicts arising from multiple txs within the same block
uint256 nonce = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), requestIdx)));
requestMsgHash = keccak256(
abi.encodePacked(
nonce,
_whitelistedAddress,
uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
)
);
requestMap[requestMsgHash] = Request({
lockId: _lockId,
callbackSelector: _callbackSelector,
callbackAddress: _callbackAddress,
idx: requestIdx,
timestamp: block.timestamp,
extended: false
});
// compute the expiry time
uint256 timeLockExpiry = block.timestamp;
if (msg.sender == primary) {
timeLockExpiry += defaultTimeLock;
} else {
timeLockExpiry += extendedTimeLock;
// any sender that is not the creator will get the extended time lock
requestMap[requestMsgHash].extended = true;
}
emit Requested(_lockId, _callbackAddress, _callbackSelector, nonce, _whitelistedAddress, requestMsgHash, timeLockExpiry);
}
/** @notice Completes a pending unlocking with two signatures.
*
* @dev Given a request message hash as two signatures of it from
* two distinct signers in the signer set, this function completes the
* unlocking of the pending request by executing the callback.
*
* @param _requestMsgHash The request message hash of a pending request.
* @param _recoveryByte1 The public key recovery byte (27 or 28)
* @param _ecdsaR1 The R component of an ECDSA signature (R, S) pair
* @param _ecdsaS1 The S component of an ECDSA signature (R, S) pair
* @param _recoveryByte2 The public key recovery byte (27 or 28)
* @param _ecdsaR2 The R component of an ECDSA signature (R, S) pair
* @param _ecdsaS2 The S component of an ECDSA signature (R, S) pair
*
* @return success True if the callback successfully executed.
*/
function completeUnlock(
bytes32 _requestMsgHash,
uint8 _recoveryByte1, bytes32 _ecdsaR1, bytes32 _ecdsaS1,
uint8 _recoveryByte2, bytes32 _ecdsaR2, bytes32 _ecdsaS2
)
public
onlySigner
returns (bool success)
{
Request storage request = requestMap[_requestMsgHash];
// copy storage to locals before `delete`
bytes32 lockId = request.lockId;
address callbackAddress = request.callbackAddress;
bytes4 callbackSelector = request.callbackSelector;
// failing case of the lookup if the callback address is zero
require(callbackAddress != address(0), "no zero value for callback address");
// reject confirms of earlier withdrawals buried under later confirmed withdrawals
require(request.idx > lastCompletedIdxs[callbackAddress][callbackSelector],
"reject confirms of earlier withdrawals buried under later confirmed withdrawals");
address signer1 = ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _requestMsgHash)),
_recoveryByte1,
_ecdsaR1,
_ecdsaS1
);
require(signerSet[signer1], "signer is set");
address signer2 = ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _requestMsgHash)),
_recoveryByte2,
_ecdsaR2,
_ecdsaS2
);
require(signerSet[signer2], "signer is set");
require(signer1 != signer2, "signers are different");
if (request.extended && ((block.timestamp - request.timestamp) < extendedTimeLock)) {
emit TimeLocked(request.timestamp + extendedTimeLock, _requestMsgHash);
return false;
} else if ((block.timestamp - request.timestamp) < defaultTimeLock) {
emit TimeLocked(request.timestamp + defaultTimeLock, _requestMsgHash);
return false;
} else {
if (address(this).balance > 0) {
// reward sender with anti-spam payments
msg.sender.transfer(address(this).balance);
}
// raise the waterline for the last completed unlocking
lastCompletedIdxs[callbackAddress][callbackSelector] = request.idx;
// and delete the request
delete requestMap[_requestMsgHash];
// invoke callback
(success,) = callbackAddress.call(abi.encodeWithSelector(callbackSelector, lockId));
if (success) {
emit Completed(lockId, _requestMsgHash, signer1, signer2);
} else {
emit Failed(lockId, _requestMsgHash, signer1, signer2);
}
}
}
/** @notice Reclaim the storage of a pending request that is uncompletable.
*
* @dev If a pending request shares the callback (address and selector) of
* a later request has been completed, then the request can no longer
* be completed. This function will reclaim the contract storage of the
* pending request.
*
* @param _requestMsgHash The request message hash of a pending request.
*/
function deleteUncompletableRequest(bytes32 _requestMsgHash) public {
Request storage request = requestMap[_requestMsgHash];
uint256 idx = request.idx;
require(0 < idx && idx < lastCompletedIdxs[request.callbackAddress][request.callbackSelector],
"there must be a completed latter request with same callback");
delete requestMap[_requestMsgHash];
}
/** @notice Extend the time lock of a pending request.
*
* @dev Requests made by the primary account receive the default time lock.
* This function allows the primary account to apply the extended time lock
* to one its own requests.
*
* @param _requestMsgHash The request message hash of a pending request.
*/
function extendRequestTimeLock(bytes32 _requestMsgHash) public onlyPrimary {
Request storage request = requestMap[_requestMsgHash];
// reject ‘null’ results from the map lookup
// this can only be the case if an unknown `_requestMsgHash` is received
require(request.callbackAddress != address(0), "reject ‘null’ results from the map lookup");
// `extendRequestTimeLock` must be idempotent
require(request.extended != true, "`extendRequestTimeLock` must be idempotent");
// set the `extended` flag; note that this is never unset
request.extended = true;
emit TimeLockExtended(request.timestamp + extendedTimeLock, _requestMsgHash);
}
}
/** @title A contract to inherit upgradeable custodianship.
*
* @notice A contract that provides re-usable code for upgradeable
* custodianship. That custodian may be an account or another contract.
*
* @dev This contract is intended to be inherited by any contract
* requiring a custodian to control some aspect of its functionality.
* This contract provides the mechanism for that custodianship to be
* passed from one custodian to the next.
*
*/
contract CustodianUpgradeable is LockRequestable {
// TYPES
/// @dev The struct type for pending custodian changes.
struct CustodianChangeRequest {
address proposedNew;
}
// MEMBERS
/// @dev The address of the account or contract that acts as the custodian.
address public custodian;
/// @dev The map of lock ids to pending custodian changes.
mapping (bytes32 => CustodianChangeRequest) public custodianChangeReqs;
// CONSTRUCTOR
constructor(
address _custodian
)
LockRequestable()
public
{
custodian = _custodian;
}
// MODIFIERS
modifier onlyCustodian {
require(msg.sender == custodian, "only custodian");
_;
}
// PUBLIC FUNCTIONS
// (UPGRADE)
/** @notice Requests a change of the custodian associated with this contract.
*
* @dev Returns a unique lock id associated with the request.
* Anyone can call this function, but confirming the request is authorized
* by the custodian.
*
* @param _proposedCustodian The address of the new custodian.
* @return lockId A unique identifier for this request.
*/
function requestCustodianChange(address _proposedCustodian) public returns (bytes32 lockId) {
require(_proposedCustodian != address(0), "no null value for `_proposedCustodian`");
lockId = generateLockId();
custodianChangeReqs[lockId] = CustodianChangeRequest({
proposedNew: _proposedCustodian
});
emit CustodianChangeRequested(lockId, msg.sender, _proposedCustodian);
}
/** @notice Confirms a pending change of the custodian associated with this contract.
*
* @dev When called by the current custodian with a lock id associated with a
* pending custodian change, the `address custodian` member will be updated with the
* requested address.
*
* @param _lockId The identifier of a pending change request.
*/
function confirmCustodianChange(bytes32 _lockId) public onlyCustodian {
custodian = getCustodianChangeReq(_lockId);
delete custodianChangeReqs[_lockId];
emit CustodianChangeConfirmed(_lockId, custodian);
}
// PRIVATE FUNCTIONS
function getCustodianChangeReq(bytes32 _lockId) private view returns (address _proposedNew) {
CustodianChangeRequest storage changeRequest = custodianChangeReqs[_lockId];
// reject ‘null’ results from the map lookup
// this can only be the case if an unknown `_lockId` is received
require(changeRequest.proposedNew != address(0), "reject ‘null’ results from the map lookup");
return changeRequest.proposedNew;
}
//EVENTS
/// @dev Emitted by successful `requestCustodianChange` calls.
event CustodianChangeRequested(
bytes32 _lockId,
address _msgSender,
address _proposedCustodian
);
/// @dev Emitted by successful `confirmCustodianChange` calls.
event CustodianChangeConfirmed(bytes32 _lockId, address _newCustodian);
}
/** @title A contract to inherit upgradeable token implementations.
*
* @notice A contract that provides re-usable code for upgradeable
* token implementations. It itself inherits from `CustodianUpgradable`
* as the upgrade process is controlled by the custodian.
*
* @dev This contract is intended to be inherited by any contract
* requiring a reference to the active token implementation, either
* to delegate calls to it, or authorize calls from it. This contract
* provides the mechanism for that implementation to be replaced,
* which constitutes an implementation upgrade.
*
*/
contract ERC20ImplUpgradeable is CustodianUpgradeable {
// TYPES
/// @dev The struct type for pending implementation changes.
struct ImplChangeRequest {
address proposedNew;
}
// MEMBERS
// @dev The reference to the active token implementation.
ERC20Impl public erc20Impl;
/// @dev The map of lock ids to pending implementation changes.
mapping (bytes32 => ImplChangeRequest) public implChangeReqs;
// CONSTRUCTOR
constructor(address _custodian) CustodianUpgradeable(_custodian) public {
erc20Impl = ERC20Impl(0x0);
}
// MODIFIERS
modifier onlyImpl {
require(msg.sender == address(erc20Impl), "only ERC20Impl");
_;
}
// PUBLIC FUNCTIONS
// (UPGRADE)
/** @notice Requests a change of the active implementation associated
* with this contract.
*
* @dev Returns a unique lock id associated with the request.
* Anyone can call this function, but confirming the request is authorized
* by the custodian.
*
* @param _proposedImpl The address of the new active implementation.
* @return lockId A unique identifier for this request.
*/
function requestImplChange(address _proposedImpl) public returns (bytes32 lockId) {
require(_proposedImpl != address(0), "no null value for `_proposedImpl`");
lockId = generateLockId();
implChangeReqs[lockId] = ImplChangeRequest({
proposedNew: _proposedImpl
});
emit ImplChangeRequested(lockId, msg.sender, _proposedImpl);
}
/** @notice Confirms a pending change of the active implementation
* associated with this contract.
*
* @dev When called by the custodian with a lock id associated with a
* pending change, the `ERC20Impl erc20Impl` member will be updated
* with the requested address.
*
* @param _lockId The identifier of a pending change request.
*/
function confirmImplChange(bytes32 _lockId) public onlyCustodian {
erc20Impl = getImplChangeReq(_lockId);
delete implChangeReqs[_lockId];
emit ImplChangeConfirmed(_lockId, address(erc20Impl));
}
// PRIVATE FUNCTIONS
function getImplChangeReq(bytes32 _lockId) private view returns (ERC20Impl _proposedNew) {
ImplChangeRequest storage changeRequest = implChangeReqs[_lockId];
// reject ‘null’ results from the map lookup
// this can only be the case if an unknown `_lockId` is received
require(changeRequest.proposedNew != address(0), "reject ‘null’ results from the map lookup");
return ERC20Impl(changeRequest.proposedNew);
}
//EVENTS
/// @dev Emitted by successful `requestImplChange` calls.
event ImplChangeRequested(
bytes32 _lockId,
address _msgSender,
address _proposedImpl
);
/// @dev Emitted by successful `confirmImplChange` calls.
event ImplChangeConfirmed(bytes32 _lockId, address _newImpl);
}
/** @title Public interface to ERC20 compliant token.
*
* @notice This contract is a permanent entry point to an ERC20 compliant
* system of contracts.
*
* @dev This contract contains no business logic and instead
* delegates to an instance of ERC20Impl. This contract also has no storage
* that constitutes the operational state of the token. This contract is
* upgradeable in the sense that the `custodian` can update the
* `erc20Impl` address, thus redirecting the delegation of business logic.
* The `custodian` is also authorized to pass custodianship.
*
*/
contract ERC20Proxy is ERC20Interface, ERC20ImplUpgradeable {
// MEMBERS
/// @notice Returns the name of the token.
string public name;
/// @notice Returns the symbol of the token.
string public symbol;
/// @notice Returns the number of decimals the token uses.
uint8 public decimals;
// CONSTRUCTOR
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
address _custodian
)
ERC20ImplUpgradeable(_custodian)
public
{
name = _name;
symbol = _symbol;
decimals = _decimals;
}
// PUBLIC FUNCTIONS
// (ERC20Interface)
/** @notice Returns the total token supply.
*
* @return the total token supply.
*/
function totalSupply() public view returns (uint256) {
return erc20Impl.totalSupply();
}
/** @notice Returns the account balance of another account with an address
* `_owner`.
*
* @return balance the balance of account with address `_owner`.
*/
function balanceOf(address _owner) public view returns (uint256 balance) {
return erc20Impl.balanceOf(_owner);
}
/** @dev Internal use only.
*/
function emitTransfer(address _from, address _to, uint256 _value) public onlyImpl {
emit Transfer(_from, _to, _value);
}
/** @notice Transfers `_value` amount of tokens to address `_to`.
*
* @dev Will fire the `Transfer` event. Will revert if the `_from`
* account balance does not have enough tokens to spend.
*
* @return success true if transfer completes.
*/
function transfer(address _to, uint256 _value) public returns (bool success) {
return erc20Impl.transferWithSender(msg.sender, _to, _value);
}
/** @notice Transfers `_value` amount of tokens from address `_from`
* to address `_to`.
*
* @dev Will fire the `Transfer` event. Will revert unless the `_from`
* account has deliberately authorized the sender of the message
* via some mechanism.
*
* @return success true if transfer completes.
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
return erc20Impl.transferFromWithSender(msg.sender, _from, _to, _value);
}
/** @dev Internal use only.
*/
function emitApproval(address _owner, address _spender, uint256 _value) public onlyImpl {
emit Approval(_owner, _spender, _value);
}
/** @notice Allows `_spender` to withdraw from your account multiple times,
* up to the `_value` amount. If this function is called again it
* overwrites the current allowance with _value.
*
* @dev Will fire the `Approval` event.
*
* @return success true if approval completes.
*/
function approve(address _spender, uint256 _value) public returns (bool success) {
return erc20Impl.approveWithSender(msg.sender, _spender, _value);
}
/** @notice Increases the amount `_spender` is allowed to withdraw from
* your account.
* This function is implemented to avoid the race condition in standard
* ERC20 contracts surrounding the `approve` method.
*
* @dev Will fire the `Approval` event. This function should be used instead of
* `approve`.
*
* @return success true if approval completes.
*/
function increaseApproval(address _spender, uint256 _addedValue) public returns (bool success) {
return erc20Impl.increaseApprovalWithSender(msg.sender, _spender, _addedValue);
}
/** @notice Decreases the amount `_spender` is allowed to withdraw from
* your account. This function is implemented to avoid the race
* condition in standard ERC20 contracts surrounding the `approve` method.
*
* @dev Will fire the `Approval` event. This function should be used
* instead of `approve`.
*
* @return success true if approval completes.
*/
function decreaseApproval(address _spender, uint256 _subtractedValue) public returns (bool success) {
return erc20Impl.decreaseApprovalWithSender(msg.sender, _spender, _subtractedValue);
}
/** @notice Returns how much `_spender` is currently allowed to spend from
* `_owner`'s balance.
*
* @return remaining the remaining allowance.
*/
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return erc20Impl.allowance(_owner, _spender);
}
}
/** @title ERC20 compliant token balance store.
*
* @notice This contract serves as the store of balances, allowances, and
* supply for the ERC20 compliant token. No business logic exists here.
*
* @dev This contract contains no business logic and instead
* is the final destination for any change in balances, allowances, or token
* supply. This contract is upgradeable in the sense that its custodian can
* update the `erc20Impl` address, thus redirecting the source of logic that
* determines how the balances will be updated.
*
*/
contract ERC20Store is ERC20ImplUpgradeable {
// MEMBERS
/// @dev The total token supply.
uint256 public totalSupply;
/// @dev The mapping of balances.
mapping (address => uint256) public balances;
/// @dev The mapping of allowances.
mapping (address => mapping (address => uint256)) public allowed;
// CONSTRUCTOR
constructor(address _custodian) ERC20ImplUpgradeable(_custodian) public {
totalSupply = 0;
}
// PUBLIC FUNCTIONS
// (ERC20 Ledger)
/** @notice The function to set the total supply of tokens.
*
* @dev Intended for use by token implementation functions
* that update the total supply. The only authorized caller
* is the active implementation.
*
* @param _newTotalSupply the value to set as the new total supply
*/
function setTotalSupply(
uint256 _newTotalSupply
)
public
onlyImpl
{
totalSupply = _newTotalSupply;
}
/** @notice Sets how much `_owner` allows `_spender` to transfer on behalf
* of `_owner`.
*
* @dev Intended for use by token implementation functions
* that update spending allowances. The only authorized caller
* is the active implementation.
*
* @param _owner The account that will allow an on-behalf-of spend.
* @param _spender The account that will spend on behalf of the owner.
* @param _value The limit of what can be spent.
*/
function setAllowance(
address _owner,
address _spender,
uint256 _value
)
public
onlyImpl
{
allowed[_owner][_spender] = _value;
}
/** @notice Sets the balance of `_owner` to `_newBalance`.
*
* @dev Intended for use by token implementation functions
* that update balances. The only authorized caller
* is the active implementation.
*
* @param _owner The account that will hold a new balance.
* @param _newBalance The balance to set.
*/
function setBalance(
address _owner,
uint256 _newBalance
)
public
onlyImpl
{
balances[_owner] = _newBalance;
}
/** @notice Adds `_balanceIncrease` to `_owner`'s balance.
*
* @dev Intended for use by token implementation functions
* that update balances. The only authorized caller
* is the active implementation.
* WARNING: the caller is responsible for preventing overflow.
*
* @param _owner The account that will hold a new balance.
* @param _balanceIncrease The balance to add.
*/
function addBalance(
address _owner,
uint256 _balanceIncrease
)
public
onlyImpl
{
balances[_owner] = balances[_owner] + _balanceIncrease;
}
}
/** @title ERC20 compliant token intermediary contract holding core logic.
*
* @notice This contract serves as an intermediary between the exposed ERC20
* interface in ERC20Proxy and the store of balances in ERC20Store. This
* contract contains core logic that the proxy can delegate to
* and that the store is called by.
*
* @dev This contract contains the core logic to implement the
* ERC20 specification as well as several extensions.
* 1. Changes to the token supply.
* 2. Batched transfers.
* 3. Relative changes to spending approvals.
* 4. Delegated transfer control ('sweeping').
*
*/
contract ERC20Impl is CustodianUpgradeable {
// TYPES
/// @dev The struct type for pending increases to the token supply (print).
struct PendingPrint {
address receiver;
uint256 value;
}
// MEMBERS
/// @dev The reference to the proxy.
ERC20Proxy public erc20Proxy;
/// @dev The reference to the store.
ERC20Store public erc20Store;
/// @dev The sole authorized caller of delegated transfer control ('sweeping').
address public sweeper;
/** @dev The static message to be signed by an external account that
* signifies their permission to forward their balance to any arbitrary
* address. This is used to consolidate the control of all accounts
* backed by a shared keychain into the control of a single key.
* Initialized as the concatenation of the address of this contract
* and the word "sweep". This concatenation is done to prevent a replay
* attack in a subsequent contract, where the sweeping message could
* potentially be replayed to re-enable sweeping ability.
*/
bytes32 public sweepMsg;
/** @dev The mapping that stores whether the address in question has
* enabled sweeping its contents to another account or not.
* If an address maps to "true", it has already enabled sweeping,
* and thus does not need to re-sign the `sweepMsg` to enact the sweep.
*/
mapping (address => bool) public sweptSet;
/// @dev The map of lock ids to pending token increases.
mapping (bytes32 => PendingPrint) public pendingPrintMap;
/// @dev The map of blocked addresses.
mapping (address => bool) public blocked;
// CONSTRUCTOR
constructor(
address _erc20Proxy,
address _erc20Store,
address _custodian,
address _sweeper
)
CustodianUpgradeable(_custodian)
public
{
require(_sweeper != address(0), "no null value for `_sweeper`");
erc20Proxy = ERC20Proxy(_erc20Proxy);
erc20Store = ERC20Store(_erc20Store);
sweeper = _sweeper;
sweepMsg = keccak256(abi.encodePacked(address(this), "sweep"));
}
// MODIFIERS
modifier onlyProxy {
require(msg.sender == address(erc20Proxy), "only ERC20Proxy");
_;
}
modifier onlySweeper {
require(msg.sender == sweeper, "only sweeper");
_;
}
/** @notice Core logic of the ERC20 `approve` function.
*
* @dev This function can only be called by the referenced proxy,
* which has an `approve` function.
* Every argument passed to that function as well as the original
* `msg.sender` gets passed to this function.
* NOTE: approvals for the zero address (unspendable) are disallowed.
*
* @param _sender The address initiating the approval in a proxy.
*/
function approveWithSender(
address _sender,
address _spender,
uint256 _value
)
public
onlyProxy
returns (bool success)
{
require(_spender != address(0), "no null value for `_spender`");
require(blocked[_sender] != true, "_sender must not be blocked");
require(blocked[_spender] != true, "_spender must not be blocked");
erc20Store.setAllowance(_sender, _spender, _value);
erc20Proxy.emitApproval(_sender, _spender, _value);
return true;
}
/** @notice Core logic of the `increaseApproval` function.
*
* @dev This function can only be called by the referenced proxy,
* which has an `increaseApproval` function.
* Every argument passed to that function as well as the original
* `msg.sender` gets passed to this function.
* NOTE: approvals for the zero address (unspendable) are disallowed.
*
* @param _sender The address initiating the approval.
*/
function increaseApprovalWithSender(
address _sender,
address _spender,
uint256 _addedValue
)
public
onlyProxy
returns (bool success)
{
require(_spender != address(0),"no null value for_spender");
require(blocked[_sender] != true, "_sender must not be blocked");
require(blocked[_spender] != true, "_spender must not be blocked");
uint256 currentAllowance = erc20Store.allowed(_sender, _spender);
uint256 newAllowance = currentAllowance + _addedValue;
require(newAllowance >= currentAllowance, "new allowance must not be smaller than previous");
erc20Store.setAllowance(_sender, _spender, newAllowance);
erc20Proxy.emitApproval(_sender, _spender, newAllowance);
return true;
}
/** @notice Core logic of the `decreaseApproval` function.
*
* @dev This function can only be called by the referenced proxy,
* which has a `decreaseApproval` function.
* Every argument passed to that function as well as the original
* `msg.sender` gets passed to this function.
* NOTE: approvals for the zero address (unspendable) are disallowed.
*
* @param _sender The address initiating the approval.
*/
function decreaseApprovalWithSender(
address _sender,
address _spender,
uint256 _subtractedValue
)
public
onlyProxy
returns (bool success)
{
require(_spender != address(0), "no unspendable approvals"); // disallow unspendable approvals
require(blocked[_sender] != true, "_sender must not be blocked");
require(blocked[_spender] != true, "_spender must not be blocked");
uint256 currentAllowance = erc20Store.allowed(_sender, _spender);
uint256 newAllowance = currentAllowance - _subtractedValue;
require(newAllowance <= currentAllowance, "new allowance must not be smaller than previous");
erc20Store.setAllowance(_sender, _spender, newAllowance);
erc20Proxy.emitApproval(_sender, _spender, newAllowance);
return true;
}
/** @notice Requests an increase in the token supply, with the newly created
* tokens to be added to the balance of the specified account.
*
* @dev Returns a unique lock id associated with the request.
* Anyone can call this function, but confirming the request is authorized
* by the custodian.
* NOTE: printing to the zero address is disallowed.
*
* @param _receiver The receiving address of the print, if confirmed.
* @param _value The number of tokens to add to the total supply and the
* balance of the receiving address, if confirmed.
*
* @return lockId A unique identifier for this request.
*/
function requestPrint(address _receiver, uint256 _value) public returns (bytes32 lockId) {
require(_receiver != address(0), "no null value for `_receiver`");
require(blocked[msg.sender] != true, "account blocked");
require(blocked[_receiver] != true, "_receiver must not be blocked");
lockId = generateLockId();
pendingPrintMap[lockId] = PendingPrint({
receiver: _receiver,
value: _value
});
emit PrintingLocked(lockId, _receiver, _value);
}
/** @notice Confirms a pending increase in the token supply.
*
* @dev When called by the custodian with a lock id associated with a
* pending increase, the amount requested to be printed in the print request
* is printed to the receiving address specified in that same request.
* NOTE: this function will not execute any print that would overflow the
* total supply, but it will not revert either.
*
* @param _lockId The identifier of a pending print request.
*/
function confirmPrint(bytes32 _lockId) public onlyCustodian {
PendingPrint storage print = pendingPrintMap[_lockId];
// reject ‘null’ results from the map lookup
// this can only be the case if an unknown `_lockId` is received
address receiver = print.receiver;
require (receiver != address(0), "unknown `_lockId`");
uint256 value = print.value;
delete pendingPrintMap[_lockId];
uint256 supply = erc20Store.totalSupply();
uint256 newSupply = supply + value;
if (newSupply >= supply) {
erc20Store.setTotalSupply(newSupply);
erc20Store.addBalance(receiver, value);
emit PrintingConfirmed(_lockId, receiver, value);
erc20Proxy.emitTransfer(address(0), receiver, value);
}
}
/** @notice Burns the specified value from the sender's balance.
*
* @dev Sender's balanced is subtracted by the amount they wish to burn.
*
* @param _value The amount to burn.
*
* @return success true if the burn succeeded.
*/
function burn(uint256 _value) public returns (bool success) {
require(blocked[msg.sender] != true, "account blocked");
uint256 balanceOfSender = erc20Store.balances(msg.sender);
require(_value <= balanceOfSender, "disallow burning more, than amount of the balance");
erc20Store.setBalance(msg.sender, balanceOfSender - _value);
erc20Store.setTotalSupply(erc20Store.totalSupply() - _value);
erc20Proxy.emitTransfer(msg.sender, address(0), _value);
return true;
}
/** @notice Burns the specified value from the balance in question.
*
* @dev Suspected balance is subtracted by the amount which will be burnt.
*
* @dev If the suspected balance has less than the amount requested, it will be set to 0.
*
* @param _from The address of suspected balance.
*
* @param _value The amount to burn.
*
* @return success true if the burn succeeded.
*/
function burn(address _from, uint256 _value) public onlyCustodian returns (bool success) {
uint256 balance = erc20Store.balances(_from);
if(_value <= balance){
erc20Store.setBalance(_from, balance - _value);
erc20Store.setTotalSupply(erc20Store.totalSupply() - _value);
erc20Proxy.emitTransfer(_from, address(0), _value);
emit Wiped(_from, _value, _value, balance - _value);
}
else {
erc20Store.setBalance(_from,0);
erc20Store.setTotalSupply(erc20Store.totalSupply() - balance);
erc20Proxy.emitTransfer(_from, address(0), balance);
emit Wiped(_from, _value, balance, 0);
}
return true;
}
/** @notice A function for a sender to issue multiple transfers to multiple
* different addresses at once. This function is implemented for gas
* considerations when someone wishes to transfer, as one transaction is
* cheaper than issuing several distinct individual `transfer` transactions.
*
* @dev By specifying a set of destination addresses and values, the
* sender can issue one transaction to transfer multiple amounts to
* distinct addresses, rather than issuing each as a separate
* transaction. The `_tos` and `_values` arrays must be equal length, and
* an index in one array corresponds to the same index in the other array
* (e.g. `_tos[0]` will receive `_values[0]`, `_tos[1]` will receive
* `_values[1]`, and so on.)
* NOTE: transfers to the zero address are disallowed.
*
* @param _tos The destination addresses to receive the transfers.
* @param _values The values for each destination address.
* @return success If transfers succeeded.
*/
function batchTransfer(address[] memory _tos, uint256[] memory _values) public returns (bool success) {
require(_tos.length == _values.length, "_tos and _values must be the same length");
require(blocked[msg.sender] != true, "account blocked");
uint256 numTransfers = _tos.length;
uint256 senderBalance = erc20Store.balances(msg.sender);
for (uint256 i = 0; i < numTransfers; i++) {
address to = _tos[i];
require(to != address(0), "no null values for _tos");
require(blocked[to] != true, "_tos must not be blocked");
uint256 v = _values[i];
require(senderBalance >= v, "insufficient funds");
if (msg.sender != to) {
senderBalance -= v;
erc20Store.addBalance(to, v);
}
erc20Proxy.emitTransfer(msg.sender, to, v);
}
erc20Store.setBalance(msg.sender, senderBalance);
return true;
}
/** @notice Enables the delegation of transfer control for many
* accounts to the sweeper account, transferring any balances
* as well to the given destination.
*
* @dev An account delegates transfer control by signing the
* value of `sweepMsg`. The sweeper account is the only authorized
* caller of this function, so it must relay signatures on behalf
* of accounts that delegate transfer control to it. Enabling
* delegation is idempotent and permanent. If the account has a
* balance at the time of enabling delegation, its balance is
* also transferred to the given destination account `_to`.
* NOTE: transfers to the zero address are disallowed.
*
* @param _vs The array of recovery byte components of the ECDSA signatures.
* @param _rs The array of 'R' components of the ECDSA signatures.
* @param _ss The array of 'S' components of the ECDSA signatures.
* @param _to The destination for swept balances.
*/
function enableSweep(uint8[] memory _vs, bytes32[] memory _rs, bytes32[] memory _ss, address _to) public onlySweeper {
require(_to != address(0), "no null value for `_to`");
require(blocked[_to] != true, "_to must not be blocked");
require((_vs.length == _rs.length) && (_vs.length == _ss.length), "_vs[], _rs[], _ss lengths are different");
uint256 numSignatures = _vs.length;
uint256 sweptBalance = 0;
for (uint256 i = 0; i < numSignatures; ++i) {
address from = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",sweepMsg)), _vs[i], _rs[i], _ss[i]);
require(blocked[from] != true, "_froms must not be blocked");
// ecrecover returns 0 on malformed input
if (from != address(0)) {
sweptSet[from] = true;
uint256 fromBalance = erc20Store.balances(from);
if (fromBalance > 0) {
sweptBalance += fromBalance;
erc20Store.setBalance(from, 0);
erc20Proxy.emitTransfer(from, _to, fromBalance);
}
}
}
if (sweptBalance > 0) {
erc20Store.addBalance(_to, sweptBalance);
}
}
/** @notice For accounts that have delegated, transfer control
* to the sweeper, this function transfers their balances to the given
* destination.
*
* @dev The sweeper account is the only authorized caller of
* this function. This function accepts an array of addresses to have their
* balances transferred for gas efficiency purposes.
* NOTE: any a...
// [truncated — 71126 bytes total]
Read Contract
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
blocked 0xe5962195 → bool
custodian 0x375b74c3 → address
custodianChangeReqs 0xcf6e4488 → address
erc20Proxy 0x7f555b03 → address
erc20Store 0xf602c312 → address
lockRequestCount 0xcb81fecf → uint256
pendingPrintMap 0x04ff7d3f → address, uint256
sweepMsg 0xde5007ff → bytes32
sweeper 0x9189a59e → address
sweptSet 0xea5fbfd5 → bool
totalSupply 0x18160ddd → uint256
Write Contract 17 functions
These functions modify contract state and require a wallet transaction to execute.
approveWithSender 0x89064fd2
address _sender
address _spender
uint256 _value
returns: bool
batchTransfer 0x88d695b2
address[] _tos
uint256[] _values
returns: bool
blockWallet 0x053e89d7
address wallet
returns: bool
burn 0x42966c68
uint256 _value
returns: bool
burn 0x9dc29fac
address _from
uint256 _value
returns: bool
confirmCustodianChange 0x3a8343ee
bytes32 _lockId
confirmPrint 0x380ba30c
bytes32 _lockId
decreaseApprovalWithSender 0x61e1077d
address _sender
address _spender
uint256 _subtractedValue
returns: bool
enableSweep 0xb7279ca6
uint8[] _vs
bytes32[] _rs
bytes32[] _ss
address _to
forceTransfer 0x33bebb77
address _from
address _to
uint256 _value
returns: bool
increaseApprovalWithSender 0x2e0179b5
address _sender
address _spender
uint256 _addedValue
returns: bool
replaySweep 0xeb55b2a3
address[] _froms
address _to
requestCustodianChange 0x15b21082
address _proposedCustodian
returns: bytes32
requestPrint 0xbe23d291
address _receiver
uint256 _value
returns: bytes32
transferFromWithSender 0x5d5e22cd
address _sender
address _from
address _to
uint256 _value
returns: bool
transferWithSender 0xdfe0f0ca
address _sender
address _to
uint256 _value
returns: bool
unblockWallet 0x1c8e1179
address wallet
returns: bool
Recent Transactions
Transaction index is loading. Only unfinalized transactions are shown while the index starts up.