Address Contract Partially Verified
Address
0x3650b99D107d581eF8ff004365A4Ada8DA6bf62F
Balance
0 ETH
Nonce
1
Code Size
11626 bytes
Creator
0x3F2dA479...e987 at tx 0x77da53a4...7cba27
Indexed Transactions
0 (1 on-chain, 1.2% indexed)
Contract Bytecode
11626 bytes
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80638beb60b61161010f578063b74d784e116100a2578063e1a9888e11610071578063e1a9888e14610fc3578063e30c397814611005578063f2fde38b1461104f578063fc0c546a14611093576101f0565b8063b74d784e14610dc6578063c3ac610d14610de4578063cb9b51c814610e71578063db518db214610f75576101f0565b8063a2d3cf4b116100de578063a2d3cf4b14610a3e578063adc4c87414610b5b578063b3ab15fb14610c60578063b619d3bd14610ca4576101f0565b80638beb60b61461087c5780638da5cb5b146108aa578063a0b9d101146108f4578063a0be06f914610a20576101f0565b8063543fd313116101875780636dd4a7c9116101565780636dd4a7c9146106ee5780636ef61092146107c457806371b150131461081c57806373d8903b1461083a576101f0565b8063543fd3131461054257806354fd4d501461059a578063570ca735146105b85780636c7a9d2414610602576101f0565b80634942e4cf116101c35780634942e4cf1461040a5780634b319713146104975780634beb62b7146104b55780634e71e0c814610538576101f0565b8063205c2878146101f5578063270231cc146102435780632e1a7d4d146102f057806332ef2b241461031e575b600080fd5b6102416004803603604081101561020b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110dd565b005b6102ee6004803603608081101561025957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001906401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460208302840111640100000000831117156102de57600080fd5b90919293919293905050506110ec565b005b61031c6004803603602081101561030657600080fd5b81019080803590602001909291905050506111a1565b005b6104086004803603608081101561033457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561038557600080fd5b82018360208201111561039757600080fd5b803590602001918460208302840111640100000000831117156103b957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506111af565b005b6104956004803603606081101561042057600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561045157600080fd5b82018360208201111561046357600080fd5b8035906020019184602083028401116401000000008311171561048557600080fd5b909192939192939050505061123e565b005b61049f611291565b6040518082815260200191505060405180910390f35b6104bd611297565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104fd5780820151818401526020810190506104e2565b50505050905090810190601f16801561052a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610540611335565b005b6105846004803603602081101561055857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061153d565b6040518082815260200191505060405180910390f35b6105a2611555565b6040518082815260200191505060405180910390f35b6105c061155b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106ec6004803603608081101561061857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561066957600080fd5b82018360208201111561067b57600080fd5b8035906020019184602083028401116401000000008311171561069d57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050611581565b005b6107ae6004803603604081101561070457600080fd5b81019080803590602001909291908035906020019064010000000081111561072b57600080fd5b82018360208201111561073d57600080fd5b8035906020019184602083028401116401000000008311171561075f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506115f4565b6040518082815260200191505060405180910390f35b610806600480360360208110156107da57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506116ab565b6040518082815260200191505060405180910390f35b6108246116c3565b6040518082815260200191505060405180910390f35b6108666004803603602081101561085057600080fd5b81019080803590602001909291905050506116c9565b6040518082815260200191505060405180910390f35b6108a86004803603602081101561089257600080fd5b81019080803590602001909291905050506116e1565b005b6108b2611865565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a1e600480360360e081101561090a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561097157600080fd5b82018360208201111561098357600080fd5b803590602001918460018302840111640100000000831117156109a557600080fd5b90919293919293908035906020019092919080359060200190929190803590602001906401000000008111156109da57600080fd5b8201836020820111156109ec57600080fd5b80359060200191846020830284011164010000000083111715610a0e57600080fd5b909192939192939050505061188b565b005b610a286119b0565b6040518082815260200191505060405180910390f35b610b4160048036036080811015610a5457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610abb57600080fd5b820183602082011115610acd57600080fd5b80359060200191846001830284011164010000000083111715610aef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506119b6565b604051808215151515815260200191505060405180910390f35b610c5e60048036036080811015610b7157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610bd857600080fd5b820183602082011115610bea57600080fd5b80359060200191846001830284011164010000000083111715610c0c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611c97565b005b610ca260048036036020811015610c7657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d26565b005b610dc4600480360360c0811015610cba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610d1757600080fd5b820183602082011115610d2957600080fd5b80359060200191846001830284011164010000000083111715610d4b57600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190640100000000811115610d8057600080fd5b820183602082011115610d9257600080fd5b80359060200191846020830284011164010000000083111715610db457600080fd5b9091929391929390505050611e70565b005b610dce611fec565b6040518082815260200191505060405180910390f35b610e6f60048036036060811015610dfa57600080fd5b81019080803590602001909291908035906020019092919080359060200190640100000000811115610e2b57600080fd5b820183602082011115610e3d57600080fd5b80359060200191846001830284011164010000000083111715610e5f57600080fd5b9091929391929390505050611ff2565b005b610f5b60048036036080811015610e8757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610ed857600080fd5b820183602082011115610eea57600080fd5b80359060200191846020830284011164010000000083111715610f0c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061219a565b604051808215151515815260200191505060405180910390f35b610fc160048036036040811015610f8b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506122ad565b005b610fef60048036036020811015610fd957600080fd5b81019080803590602001909291905050506122bc565b6040518082815260200191505060405180910390f35b61100d6122d4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110916004803603602081101561106557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122fa565b005b61109b612401565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110e8823383612427565b5050565b611139843385858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b600061118d600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b905061119986826110dd565b505050505050565b6111ac333383612427565b50565b6111bb8484848461219a565b61122d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6572726f725f70726f6f6600000000000000000000000000000000000000000081525060200191505060405180910390fd5b6112388484846127ad565b50505050565b61128b338585858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050611581565b50505050565b60085481565b600c8054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561132d5780601f106113025761010080835404028352916020019161132d565b820191906000526020600020905b81548152906001019060200180831161131057829003601f168201915b505050505081565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146113f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6572726f725f6f6e6c7950656e64696e674f776e65720000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600a6020528060005260406000206000915090505481565b600d5481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61158d838584846111af565b60006115e1600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548461276390919063ffffffff16565b90506115ed85826122ad565b5050505050565b600082905060008090505b82518160ff1610156116a4576000838260ff168151811061161c57fe5b60200260200101519050808310156116645782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250611696565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b5080806001019150506115ff565b5092915050565b600b6020528060005260406000206000915090505481565b60035481565b60046020528060005260406000206000915090505481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b670de0b6b3a7640000811115611822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f61646d696e46656500000000000000000000000000000000000081525060200191505060405180910390fd5b806006819055507f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534876006546040518082815260200191505060405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6118db89898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b61194d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b61199a848985858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6119a5898989612427565b505050505050505050565b60065481565b60006041825114611a2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f6572726f725f6261645369676e61747572654c656e677468000000000000000081525060200191505060405180910390fd5b60008060006020850151925060408501519150606085015160001a9050601b8160ff161015611a5f57601b810190505b601b8160ff161480611a745750601c8160ff16145b611ae6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6572726f725f6261645369676e617475726556657273696f6e0000000000000081525060200191505060405180910390fd5b6000888730600b60008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313034000000815250601d018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001945050505050604051602081830303815290604052805190602001209050600060018284878760405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611c4d573d6000803e3d6000fd5b5050506020604051035190508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161495505050505050949350505050565b611ca3848484846119b6565b611d15576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611d20848484612427565b50505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611de9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5460405160405180910390a250565b611ec18888600089898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b611f33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611f80848885858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6000611fd4600b60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b9050611fe1898983612427565b505050505050505050565b60095481565b6000801b600080868152602001908152602001600020541461207c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665727772697465000000000000000000000000000000000081525060200191505060405180910390fd5b606082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506120d0858583612b0d565b83600080878152602001908152602001600020819055507f444dcb3cce8fbb3e1dabd2ff958f17fb1e673b759824d631d9cda0690d031eb98585836040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561215757808201518184015260208101905061213c565b50505050905090810190601f1680156121845780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15050505050565b600080848487604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401838152602001828152602001935050505060405160208183030381529060405280519060200120905060008060008881526020019081526020016000205490506000801b811415612295576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f6572726f725f626c6f636b4e6f74466f756e640000000000000000000000000081525060200191505060405180910390fd5b61229f82856115f4565b811492505050949350505050565b6122b8828383612427565b5050565b60006020528060005260406000206000915090505481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146123bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161249d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f7a65726f5769746864726177000000000000000000000000000081525060200191505060405180910390fd5b60006124f182600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612bed90919063ffffffff16565b9050600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548111156125a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665726472616674000000000000000000000000000000000081525060200191505060405180910390fd5b80600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061260182600854612bed90919063ffffffff16565b600881905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156126b057600080fd5b505af11580156126c4573d6000803e3d6000fd5b505050506040513d60208110156126da57600080fd5b810190808051906020019092919050505061275d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f7472616e7366657200000000000000000000000000000000000081525060200191505060405180910390fd5b50505050565b60006127a583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c75565b905092915050565b6000600460008581526020019081526020016000205490506003548101421161283e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f6572726f725f66726f7a656e000000000000000000000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054106128f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6572726f725f6f6c644561726e696e677300000000000000000000000000000081525060200191505060405180910390fd5b612958600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461294a84600954612bed90919063ffffffff16565b61276390919063ffffffff16565b600981905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129fd57600080fd5b505afa158015612a11573d6000803e3d6000fd5b505050506040513d6020811015612a2757600080fd5b8101908080519060200190929190505050612a4f60085460095461276390919063ffffffff16565b1115612ac3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6572726f725f6d697373696e6742616c616e636500000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612bd0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6e6f745065726d6974746564000000000000000000000000000081525060200191505060405180910390fd5b426004600085815260200190815260200160002081905550505050565b600080828401905083811015612c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000838311158290612d22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612ce7578082015181840152602081019050612ccc565b50505050905090810190601f168015612d145780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838503905080915050939250505056fea265627a7a723158206640614c1e318d8144727db96b3e60f3980eab48f5ee5fb614332bd1b358b38464736f6c63430005100032
Verified Source Code Partial Match
Compiler: v0.5.16+commit.9c3226ce
EVM: istanbul
Optimization: No
DataunionVault.sol 709 lines
pragma solidity ^0.5.16;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* Abstract contract, requires implementation to specify who can commit blocks and what
* happens when a successful proof is presented
* Verifies Merkle-tree inclusion proofs that show that certain address has
* certain earnings balance, according to hash published ("signed") by a
* sidechain operator or similar authority
*
* ABOUT Merkle-tree inclusion proof: Merkle-tree inclusion proof is an algorithm to prove memebership
* in a set using minimal [ie log(N)] inputs. The hashes of the items are arranged by hash value in a binary Merkle tree where
* each node contains a hash of the hashes of nodes below. The root node (ie "root hash") contains hash information
* about the entire set, and that is the data that BalanceVerifier posts to the blockchain. To prove membership, you walk up the
* tree from the node in question, and use the supplied hashes (the "proof") to fill in the hashes from the adjacent nodes. The proof
* succeeds iff you end up with the known root hash when you get to the top of the tree.
* See https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5
*
* Merkle-tree inclusion proof is a related concept to the blockchain Merkle tree, but a somewhat different application.
* BalanceVerifier posts the root hash of the current ledger only, and this does not depend on the hash of previous ledgers.
* This is different from the blockchain, where each block contains the hash of the previous block.
*
* TODO: see if it could be turned into a library, so many contracts could use it
*/
contract BalanceVerifier {
event NewCommit(uint blockNumber, bytes32 rootHash, string ipfsHash);
/**
* Root hashes of merkle-trees constructed from its balances
* @param uint root-chain block number after which the balances were committed
* @return bytes32 root of the balances merkle-tree at that time
*/
mapping (uint => bytes32) public committedHash;
/**
* Handler for proof of off-chain balances
* It is up to the implementing contract to actually distribute out the balances
* @param blockNumber the block whose hash was used for verification
* @param account whose balances were successfully verified
* @param balance the off-chain account balance
*/
function onVerifySuccess(uint blockNumber, address account, uint balance) internal;
/**
* Implementing contract should should do access controls for committing
*/
function onCommit(uint blockNumber, bytes32 rootHash, string memory ipfsHash) internal;
/**
* Monoplasma operator submits commitments to root-chain.
* For convenience, also publish the ipfsHash of the balance book JSON object
* @param blockNumber the root-chain block after which the balances were recorded
* @param rootHash root of the balances merkle-tree
* @param ipfsHash where the whole balances object can be retrieved in JSON format
*/
function commit(uint blockNumber, bytes32 rootHash, string calldata ipfsHash) external {
require(committedHash[blockNumber] == 0, "error_overwrite");
string memory _hash = ipfsHash;
onCommit(blockNumber, rootHash, _hash); // Access control delegated to implementing class
committedHash[blockNumber] = rootHash;
emit NewCommit(blockNumber, rootHash, _hash);
}
/**
* Proving can be used to record the sidechain balances permanently into root chain
* @param blockNumber the block after which the balances were recorded
* @param account whose balances will be verified
* @param balance off-chain account balance
* @param proof list of hashes to prove the totalEarnings
*/
function prove(uint blockNumber, address account, uint balance, bytes32[] memory proof) public {
require(proofIsCorrect(blockNumber, account, balance, proof), "error_proof");
onVerifySuccess(blockNumber, account, balance);
}
/**
* Check the merkle proof of balance in the given commit (after blockNumber in root-chain) for given account
* @param blockNumber the block after which the balances were recorded
* @param account whose balances will be verified
* @param balance off-chain account balance
* @param proof list of hashes to prove the totalEarnings
*/
function proofIsCorrect(uint blockNumber, address account, uint balance, bytes32[] memory proof) public view returns(bool) {
bytes32 leafHash = keccak256(abi.encodePacked(account, balance, blockNumber));
bytes32 rootHash = committedHash[blockNumber];
require(rootHash != 0x0, "error_blockNotFound");
return rootHash == calculateRootHash(leafHash, proof);
}
/**
* Calculate root hash of a Merkle tree, given
* @param leafHash of the member whose balances are being be verified
* @param others list of hashes of "other" branches
*/
function calculateRootHash(bytes32 leafHash, bytes32[] memory others) public pure returns (bytes32 root) {
root = leafHash;
for (uint8 i = 0; i < others.length; i++) {
bytes32 other = others[i];
if (root < other) {
// TODO: consider hashing in i to defend from https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
root = keccak256(abi.encodePacked(root, other));
} else {
root = keccak256(abi.encodePacked(other, root));
}
}
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
address public pendingOwner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner, "error_onlyOwner");
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() public {
require(msg.sender == pendingOwner, "error_onlyPendingOwner");
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
}
}
/**
* Monoplasma that is managed by an owner, who also appoints a trusted (but verifiable) operator.
* Owner should be able to add and remove recipients through an off-chain mechanism not specified here.
*/
contract Monoplasma is BalanceVerifier, Ownable {
using SafeMath for uint256;
event OperatorChanged(address indexed newOperator);
event AdminFeeChanged(uint adminFee);
/**
* Freeze period during which all participants should be able to
* acquire the whole balance book from IPFS (or HTTP server, or elsewhere)
* and validate that the published rootHash is correct.
* In case of incorrect rootHash, all members should issue withdrawals from the
* latest block they have validated (that is older than blockFreezeSeconds).
* So: too short freeze period `+` bad availability `=>` ether (needlessly) spent withdrawing earnings.
* Long freeze period `==` lag between purchase and withdrawal `=>` bad UX.
* Blocks older than blockFreezeSeconds can be used to withdraw funds.
*/
uint public blockFreezeSeconds;
/**
* Block number => timestamp
* Publish time of a block, where the block freeze period starts from.
* Note that block number points to the block after which the root hash is calculated,
* not the block where NewCommit was emitted (event must come later)
*/
mapping (uint => uint) public blockTimestamp;
/// operator is the address who is allowed to commit the earnings
address public operator;
/// fee fraction = adminFee/10^18
uint public adminFee;
IERC20 public token;
/// track lifetime total of tokens withdrawn from contract
uint public totalWithdrawn;
/**
* Track lifetime total of earnings proven, as extra protection from malicious operator.
* The difference of what CAN be withdrawn and what HAS been withdrawn must be covered with tokens in contract,
* in other words: `totalProven - totalWithdrawn <= token.balanceOf(this)`.
* This is to prevent a "bank run" situation where more earnings have been proven in the contract than there are tokens to cover them.
* Of course this only moves the "bank run" outside the contract, to a race to prove earnings,
* but at least the contract should never go into a state where it couldn't cover what's been proven.
*/
uint public totalProven;
/// earnings for which proof has been submitted
mapping (address => uint) public earnings;
/// earnings that have been sent out already
mapping (address => uint) public withdrawn;
constructor(address tokenAddress, uint blockFreezePeriodSeconds, uint initialAdminFee) public {
blockFreezeSeconds = blockFreezePeriodSeconds;
token = IERC20(tokenAddress);
operator = msg.sender;
setAdminFee(initialAdminFee);
}
/**
* Admin can appoint the operator.
* @param newOperator that is allowed to commit the off-chain balances
*/
function setOperator(address newOperator) public onlyOwner {
operator = newOperator;
emit OperatorChanged(newOperator);
}
/**
* Admin fee as a fraction of revenue.
* Smart contract doesn't use it, it's here just for storing purposes.
* @param newAdminFee fixed-point decimal in the same way as ether: 50% === 0.5 ether === "500000000000000000"
*/
function setAdminFee(uint newAdminFee) public onlyOwner {
require(newAdminFee <= 1 ether, "error_adminFee");
adminFee = newAdminFee;
emit AdminFeeChanged(adminFee);
}
/**
* Operator commits the off-chain balances.
* This starts the freeze period (measured from block.timestamp).
* See README under "Threat model" for discussion on safety of using "now".
* @param blockNumber after which balances were submitted
*/
function onCommit(uint blockNumber, bytes32, string memory) internal {
require(msg.sender == operator, "error_notPermitted");
blockTimestamp[blockNumber] = now; // solium-disable-line security/no-block-members
}
/**
* Called from BalanceVerifier.prove.
* Prove can be called directly to withdraw less than the whole share,
* or just "cement" the earnings so far into root chain even without withdrawing.
* Missing balance test is an extra layer of defense against fraudulent operator who tries to steal ALL tokens.
* If any member can exit within freeze period, that fraudulent commit will fail.
* Only earnings that have been committed longer than blockFreezeSeconds ago can be proven, see `onCommit`.
* See README under "Threat model" for discussion on safety of using "now".
* @param blockNumber after which balances were submitted in {onCommit}
* @param account whose earnings were successfully proven and updated
* @param newEarnings the updated total lifetime earnings
*/
function onVerifySuccess(uint blockNumber, address account, uint newEarnings) internal {
uint blockFreezeStart = blockTimestamp[blockNumber];
require(now > blockFreezeStart + blockFreezeSeconds, "error_frozen"); // solium-disable-line security/no-block-members
require(earnings[account] < newEarnings, "error_oldEarnings");
totalProven = totalProven.add(newEarnings).sub(earnings[account]);
require(totalProven.sub(totalWithdrawn) <= token.balanceOf(address(this)), "error_missingBalance");
earnings[account] = newEarnings;
}
/**
* Prove and withdraw the whole revenue share from sidechain in one transaction.
* @param blockNumber of the commit that contains the earnings to verify
* @param totalEarnings in the off-chain balance book
* @param proof list of hashes to prove the totalEarnings
*/
function withdrawAll(uint blockNumber, uint totalEarnings, bytes32[] calldata proof) external {
withdrawAllFor(msg.sender, blockNumber, totalEarnings, proof);
}
/**
* Prove and withdraw the whole revenue share on behalf of someone else.
* Validator needs to exit those it's watching out for, in case
* it detects Operator malfunctioning.
* @param recipient the address we're proving and withdrawing to
* @param blockNumber of the commit that contains the earnings to verify
* @param totalEarnings in the off-chain balance book
* @param proof list of hashes to prove the totalEarnings
*/
function withdrawAllFor(address recipient, uint blockNumber, uint totalEarnings, bytes32[] memory proof) public {
prove(blockNumber, recipient, totalEarnings, proof);
uint withdrawable = totalEarnings.sub(withdrawn[recipient]);
withdrawFor(recipient, withdrawable);
}
/**
* Prove and "donate withdraw" function that allows you to prove and transfer
* your earnings to a another address in one transaction.
* @param recipient the address the tokens will be sent to (instead of msg.sender)
* @param blockNumber of the commit that contains the earnings to verify
* @param totalEarnings in the off-chain balance book
* @param proof list of hashes to prove the totalEarnings
*/
function withdrawAllTo(address recipient, uint blockNumber, uint totalEarnings, bytes32[] calldata proof) external {
prove(blockNumber, msg.sender, totalEarnings, proof);
uint withdrawable = totalEarnings.sub(withdrawn[msg.sender]);
withdrawTo(recipient, withdrawable);
}
/**
* Prove and do an "unlimited donate withdraw" on behalf of someone else, to an address they've specified.
* Sponsored withdraw is paid by e.g. admin, but target account could be whatever the member specifies.
* The signature gives a "blank cheque" for admin to withdraw all tokens to `recipient` in the future,
* and it's valid until next withdraw (and so can be nullified by withdrawing any amount).
* A new signature needs to be obtained for each subsequent future withdraw.
* @param recipient the address the tokens will be sent to (instead of `msg.sender`)
* @param signer whose earnings are being withdrawn
* @param signature from the community member, see `signatureIsValid` how signature generated for unlimited amount
* @param blockNumber of the commit that contains the earnings to verify
* @param totalEarnings in the off-chain balance book
* @param proof list of hashes to prove the totalEarnings
*/
function withdrawAllToSigned(
address recipient,
address signer, bytes calldata signature, // signature arguments
uint blockNumber, uint totalEarnings, bytes32[] calldata proof // proof arguments
)
external
{
require(signatureIsValid(recipient, signer, 0, signature), "error_badSignature");
prove(blockNumber, signer, totalEarnings, proof);
uint withdrawable = totalEarnings.sub(withdrawn[signer]);
_withdraw(recipient, signer, withdrawable);
}
/**
* Prove and do a "donate withdraw" on behalf of someone else, to an address they've specified.
* Sponsored withdraw is paid by e.g. admin, but target account could be whatever the member specifies.
* The signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens.
* @param recipient the address the tokens will be sent to (instead of msg.sender)
* @param signer whose earnings are being withdrawn
* @param amount of tokens to withdraw
* @param signature from the community member, see `signatureIsValid` how it's generated
* @param blockNumber of the commit that contains the earnings to verify
* @param totalEarnings in the off-chain balance book
* @param proof list of hashes to prove the totalEarnings
*/
function proveAndWithdrawToSigned(
address recipient,
address signer, uint amount, bytes calldata signature, // signature arguments
uint blockNumber, uint totalEarnings, bytes32[] calldata proof // proof arguments
)
external
{
require(signatureIsValid(recipient, signer, amount, signature), "error_badSignature");
prove(blockNumber, signer, totalEarnings, proof);
_withdraw(recipient, signer, amount);
}
/**
* Withdraw a specified amount of your own proven earnings (see `function prove`).
* @param amount of tokens to withdraw
*/
function withdraw(uint amount) public {
_withdraw(msg.sender, msg.sender, amount);
}
/**
* Withdraw a specified amount on behalf of someone else.
* Validator needs to exit those it's watching out for, in case it detects Operator malfunctioning.
* @param recipient whose tokens will be withdrawn (instead of msg.sender)
* @param amount of tokens to withdraw
*/
function withdrawFor(address recipient, uint amount) public {
_withdraw(recipient, recipient, amount);
}
/**
* "Donate withdraw":
* Withdraw and transfer proven earnings to a another address in one transaction,
* instead of withdrawing and then transfering the tokens.
* @param recipient the address the tokens will be sent to (instead of `msg.sender`)
* @param amount of tokens to withdraw
*/
function withdrawTo(address recipient, uint amount) public {
_withdraw(recipient, msg.sender, amount);
}
/**
* Signed "donate withdraw":
* Withdraw and transfer proven earnings to a third address on behalf of someone else.
* Sponsored withdraw is paid by e.g. admin, but target account could be whatever the member specifies.
* @param recipient of the tokens
* @param signer whose earnings are being withdrawn
* @param amount how much is authorized for withdrawing by the signature
* @param signature from the community member, see `signatureIsValid` how it's generated
*/
function withdrawToSigned(address recipient, address signer, uint amount, bytes memory signature) public {
require(signatureIsValid(recipient, signer, amount, signature), "error_badSignature");
_withdraw(recipient, signer, amount);
}
/**
* Execute token withdrawal into specified recipient address from specified member account.
* To prevent "bank runs", it is up to the sidechain implementation to make sure that always:
* `sum of committed earnings <= token.balanceOf(this) + totalWithdrawn`.
* Smart contract can't verify that, because it can't see inside the commit hash.
* @param recipient of the tokens
* @param account whose earnings are being debited
* @param amount of tokens that is sent out
*/
function _withdraw(address recipient, address account, uint amount) internal {
require(amount > 0, "error_zeroWithdraw");
uint w = withdrawn[account].add(amount);
require(w <= earnings[account], "error_overdraft");
withdrawn[account] = w;
totalWithdrawn = totalWithdrawn.add(amount);
require(token.transfer(recipient, amount), "error_transfer");
}
/**
* Check signature from a member authorizing withdrawing its earnings to another account.
* Throws if the signature is badly formatted or doesn't match the given signer and amount.
* Signature has parts the act as replay protection:
* 1) `address(this)`: signature can't be used for other contracts;
* 2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be "cancelled" by sending a withdraw tx.
* Generated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`,
* or for unlimited amount: `web3.eth.accounts.sign(recipientAddress + "0".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`.
* @param recipient of the tokens
* @param signer whose earnings are being withdrawn
* @param amount how much is authorized for withdraw, or zero for unlimited (withdrawAll)
* @param signature byte array from `web3.eth.accounts.sign`
* @return true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature
*/
function signatureIsValid(address recipient, address signer, uint amount, bytes memory signature) public view returns (bool isValid) {
require(signature.length == 65, "error_badSignatureLength");
bytes32 r; bytes32 s; uint8 v;
assembly { // solium-disable-line security/no-inline-assembly
r := mload(add(signature, 32))
s := mload(add(signature, 64))
v := byte(0, mload(add(signature, 96)))
}
if (v < 27) {
v += 27;
}
require(v == 27 || v == 28, "error_badSignatureVersion");
// When changing the message, remember to double-check that message length is correct!
bytes32 messageHash = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n104", recipient, amount, address(this), withdrawn[signer]));
address calculatedSigner = ecrecover(messageHash, v, r, s);
return calculatedSigner == signer;
}
}
contract DataunionVault is Monoplasma {
string public joinPartStream;
/** Server version. This must be kept in sync with src/server.js */
uint public version = 1;
constructor(address operator, string memory joinPartStreamId, address tokenAddress, uint blockFreezePeriodSeconds, uint adminFeeFraction)
Monoplasma(tokenAddress, blockFreezePeriodSeconds, adminFeeFraction) public {
setOperator(operator);
joinPartStream = joinPartStreamId;
}
}
Read Contract
adminFee 0xa0be06f9 → uint256
blockFreezeSeconds 0x71b15013 → uint256
blockTimestamp 0x73d8903b → uint256
calculateRootHash 0x6dd4a7c9 → bytes32
committedHash 0xe1a9888e → bytes32
earnings 0x543fd313 → uint256
joinPartStream 0x4beb62b7 → string
operator 0x570ca735 → address
owner 0x8da5cb5b → address
pendingOwner 0xe30c3978 → address
proofIsCorrect 0xcb9b51c8 → bool
signatureIsValid 0xa2d3cf4b → bool
token 0xfc0c546a → address
totalProven 0xb74d784e → uint256
totalWithdrawn 0x4b319713 → uint256
version 0x54fd4d50 → uint256
withdrawn 0x6ef61092 → uint256
Write Contract 15 functions
These functions modify contract state and require a wallet transaction to execute.
claimOwnership 0x4e71e0c8
No parameters
commit 0xc3ac610d
uint256 blockNumber
bytes32 rootHash
string ipfsHash
prove 0x32ef2b24
uint256 blockNumber
address account
uint256 balance
bytes32[] proof
proveAndWithdrawToSigned 0xa0b9d101
address recipient
address signer
uint256 amount
bytes signature
uint256 blockNumber
uint256 totalEarnings
bytes32[] proof
setAdminFee 0x8beb60b6
uint256 newAdminFee
setOperator 0xb3ab15fb
address newOperator
transferOwnership 0xf2fde38b
address newOwner
withdraw 0x2e1a7d4d
uint256 amount
withdrawAll 0x4942e4cf
uint256 blockNumber
uint256 totalEarnings
bytes32[] proof
withdrawAllFor 0x6c7a9d24
address recipient
uint256 blockNumber
uint256 totalEarnings
bytes32[] proof
withdrawAllTo 0x270231cc
address recipient
uint256 blockNumber
uint256 totalEarnings
bytes32[] proof
withdrawAllToSigned 0xb619d3bd
address recipient
address signer
bytes signature
uint256 blockNumber
uint256 totalEarnings
bytes32[] proof
withdrawFor 0xdb518db2
address recipient
uint256 amount
withdrawTo 0x205c2878
address recipient
uint256 amount
withdrawToSigned 0xadc4c874
address recipient
address signer
uint256 amount
bytes signature
Recent Transactions
This address has 1 on-chain transactions, but only 1.2% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →