Address Contract Partially Verified
Address
0x2dCaD61350EC531910Da683d396d92e3aE5E5C8d
Balance
0 ETH
Nonce
1
Code Size
9063 bytes
Creator
0xA2D9846c...8a78 at tx 0x2e8901c6...f02e4e
Indexed Transactions
0 (1 on-chain, 1.4% indexed)
Contract Bytecode
9063 bytes
0x608060405234801561001057600080fd5b50600436106102d55760003560e01c80637ba8c82011610182578063a9059cbb116100e9578063cf309012116100a2578063e4cd1aec1161007c578063e4cd1aec146106f2578063ef40a67014610718578063f2fde38b1461073e578063f83d08ba14610764576102d5565b8063cf309012146106b4578063dd62ed3e146106bc578063df5cf723146106ea576102d5565b8063a9059cbb146105e5578063abf59fc914610611578063b37f259014610647578063b4988fd014610670578063bfb18f29146106a4578063c7b8981c146106ac576102d5565b80638f32d59b1161013b5780638f32d59b146105765780639b2cb5d81461057e578063a22a642814610586578063a446c2db146105a9578063a457c2d7146105b1578063a69df4b5146105dd576102d5565b80637ba8c820146104f85780638b0e9f3f146105175780638d086da41461051f5780638d16a14a146105275780638d23fc611461052f5780638da5cb5b1461056e576102d5565b8063446a2ec811610241578063676e5550116101fa57806370a08231116101d457806370a08231146104ba578063715018a6146104e0578063753868e3146104e85780637542ff95146104f0576102d5565b8063676e5550146104545780636ab150711461047a5780636c7518971461049d576102d5565b8063446a2ec8146104245780634f91440d1461042c5780635c42c733146104345780635c5f7dae1461043c5780635d1e3616146104445780635ea1d6f81461044c576102d5565b806323b872dd1161029357806323b872dd1461038657806332ba2e53146103bc57806339509351146103c45780633a09bf44146103f05780633ba0b9a9146103f85780633d94eb0514610400576102d5565b8062fa3d50146102da578063095ea7b3146102f95780630d331908146103395780630d58a5f31461035c57806318160ddd1461037657806322f0f2f91461037e575b600080fd5b6102f7600480360360208110156102f057600080fd5b503561076c565b005b6103256004803603604081101561030f57600080fd5b506001600160a01b038135169060200135610a34565b604080519115158252519081900360200190f35b6102f76004803603604081101561034f57600080fd5b5080359060200135610a4b565b610364610a85565b60408051918252519081900360200190f35b610364610a8b565b610364610a91565b6103256004803603606081101561039c57600080fd5b506001600160a01b03813581169160208101359091169060400135610ab3565b610364610b0a565b610325600480360360408110156103da57600080fd5b506001600160a01b038135169060200135610b2a565b610364610b66565b610364610b6c565b610408610bb3565b604080516001600160a01b039092168252519081900360200190f35b610364610bc2565b6102f7610bc8565b610364610cbd565b610364610cc3565b610364610cc9565b610364610ccf565b6103646004803603602081101561046a57600080fd5b50356001600160a01b0316610cd5565b6102f76004803603604081101561049057600080fd5b5080359060200135610d49565b6102f7600480360360208110156104b357600080fd5b5035610e2d565b610364600480360360208110156104d057600080fd5b50356001600160a01b0316611160565b6102f761117b565b6103646111dc565b6104086111f7565b6102f76004803603602081101561050e57600080fd5b50351515611206565b61036461122a565b610364611230565b6102f7611236565b6105556004803603602081101561054557600080fd5b50356001600160a01b0316611554565b6040805192835260208301919091528051918290030190f35b61040861156d565b610325611581565b610364611597565b6103646004803603604081101561059c57600080fd5b508035906020013561159d565b61036461165c565b610325600480360360408110156105c757600080fd5b506001600160a01b038135169060200135611662565b6102f761169e565b610325600480360360408110156105fb57600080fd5b506001600160a01b0381351690602001356116b9565b6102f76004803603606081101561062757600080fd5b506001600160a01b038135811691602081013590911690604001356116c6565b6103646004803603606081101561065d57600080fd5b50803590602081013590604001356117ed565b6102f76004803603606081101561068657600080fd5b508035906001600160a01b0360208201358116916040013516611845565b610364611904565b6102f761192a565b610325611990565b610364600480360360408110156106d257600080fd5b506001600160a01b0381358116916020013516611999565b6103256119c4565b6103646004803603602081101561070857600080fd5b50356001600160a01b03166119cd565b6103646004803603602081101561072e57600080fd5b50356001600160a01b03166119df565b6102f76004803603602081101561075457600080fd5b50356001600160a01b03166119f1565b6102f7611a0b565b600554600654604080516331a9108f60e11b815260048101929092525133926001600160a01b031691636352211e916024808301926020929190829003018186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050506040513d60208110156107e457600080fd5b50516001600160a01b031614610831576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6005546040805163900cf0cf60e01b815290516000926001600160a01b03169163900cf0cf916004808301926020929190829003018186803b15801561087657600080fd5b505afa15801561088a573d6000803e3d6000fd5b505050506040513d60208110156108a057600080fd5b50516009546005546040805163a7ab696160e01b815290519394509192849261092c926001600160a01b03169163a7ab696191600480820192602092909190829003018186803b1580156108f357600080fd5b505afa158015610907573d6000803e3d6000fd5b505050506040513d602081101561091d57600080fd5b5051839063ffffffff611a2416565b111580610937575080155b6109725760405162461bcd60e51b815260040180806020018281038252602681526020018061230d6026913960400191505060405180910390fd5b60648311156109b25760405162461bcd60e51b815260040180806020018281038252602b8152602001806122e2602b913960400191505060405180910390fd5b60048054600654600854604080516364c6600160e11b815294850192909252602484018790526044840152516001600160a01b039091169163c98cc00291606480830192600092919082900301818387803b158015610a1057600080fd5b505af1158015610a24573d6000803e3d6000fd5b5050506008939093555060095550565b6000610a41338484611a3d565b5060015b92915050565b610a53611581565b610a5c57600080fd5b6000610a73600d5483611a2490919063ffffffff16565b9050610a80838383611ac5565b505050565b60095481565b60025490565b6000610a9b611581565b610aa457600080fd5b610aac61169e565b50600d5490565b6000610ac0848484611b90565b6001600160a01b038416600090815260016020908152604080832033808552925290912054610b00918691610afb908663ffffffff611bc816565b611a3d565b5060019392505050565b6000610b14611581565b610b1d57600080fd5b5060078054600090915590565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a41918590610afb908663ffffffff611a2416565b600d5481565b600080610b77610a8b565b90508015610baa57610ba581610b996064600d54611bdd90919063ffffffff16565b9063ffffffff611c0416565b610bad565b60645b91505090565b6004546001600160a01b031681565b600c5481565b6000610bd333611c26565b9050600a54811015610c2c576040805162461bcd60e51b815260206004820152601c60248201527f546f6f20736d616c6c207265776172647320746f2072657374616b6500000000604482015290519081900360640190fd5b610c37816000611c56565b506004805460065433600081815260116020526040808220548151637f88a95760e01b81529687019490945260248601929092526044850192909252516001600160a01b0390921692637f88a957926064808301939282900301818387803b158015610ca257600080fd5b505af1158015610cb6573d6000803e3d6000fd5b5050505050565b600f5481565b60065481565b60075481565b60085481565b600080610ce183611160565b905080610cf2576000915050610d44565b6001600160a01b038316600090815260136020526040902054600c54610d40916a084595161401484a00000091610b99918591610d349163ffffffff611bc816565b9063ffffffff611bdd16565b9150505b919050565b610d51611f5d565b506000610d5e8383611c56565b60055460065460408051636901b25360e01b8152600481019290925260248201849052336044830152519293506001600160a01b0390911691636901b253916064808201926020929091908290030181600087803b158015610dbf57600080fd5b505af1158015610dd3573d6000803e3d6000fd5b505050506040513d6020811015610de957600080fd5b5051610a80576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b6000610e3833611160565b905060008111610e7e576040805162461bcd60e51b815260206004820152600c60248201526b5a65726f2062616c616e636560a01b604482015290519081900360640190fd5b6000610e88610b6c565b90506000610ea16064610b99848663ffffffff611bdd16565b905083811015610eec576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b610ef4611f5d565b50610eff33846120bc565b60055460065460408051629ff11560e81b815260048101929092526000848103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b158015610f5557600080fd5b505af1158015610f69573d6000803e3d6000fd5b5050600d54610f81925090508263ffffffff611bc816565b600d556000610fa2610f91611904565b610b9984606463ffffffff611bdd16565b600f54909150610fb8908363ffffffff611a2416565b600f55601054610fce908263ffffffff611a2416565b601055604080518082018252828152600554825163900cf0cf60e01b8152925191926020808501936001600160a01b039093169263900cf0cf926004808201939291829003018186803b15801561102457600080fd5b505afa158015611038573d6000803e3d6000fd5b505050506040513d602081101561104e57600080fd5b5051905233600081815260126020908152604080832085518155948201516001909501949094556011905282812081905560048054600654855163f1382b5360e01b8152928301526024820193909352604481018690526064810188905292516001600160a01b0390921692839263f1382b539260848084019391929182900301818387803b1580156110e057600080fd5b505af11580156110f4573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561114057600080fd5b505af1158015611154573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b031660009081526020819052604090205490565b611183611581565b61118c57600080fd5b60035460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360038054610100600160a81b0319169055565b60006111e6611581565b6111ef57600080fd5b610aac611a0b565b6005546001600160a01b031681565b61120e611581565b61121757600080fd5b600e805460ff1916911515919091179055565b600b5481565b60105481565b336000908152601260209081526040918290208054600554845163900cf0cf60e01b81529451929491936001600160a01b039091169263900cf0cf926004808201939291829003018186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d60208110156112b857600080fd5b50516005546040805163a7ab696160e01b8152905161133d926001600160a01b03169163a7ab6961916004808301926020929190829003018186803b15801561130057600080fd5b505afa158015611314573d6000803e3d6000fd5b505050506040513d602081101561132a57600080fd5b505160018501549063ffffffff611a2416565b1115801561134b5750600081115b61139c576040805162461bcd60e51b815260206004820152601c60248201527f496e636f6d706c657465207769746864726177616c20706572696f6400000000604482015290519081900360640190fd5b60006113af6064610b9984610d34611904565b6010549091506113c5908363ffffffff611bc816565b601055600f546113db908263ffffffff611bc816565b600f55600b546113f1908263ffffffff611bc816565b600b556005546006546040805163bc8756a960e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163bc8756a9916064808201926020929091908290030181600087803b15801561145257600080fd5b505af1158015611466573d6000803e3d6000fd5b505050506040513d602081101561147c57600080fd5b50516114c5576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163302df4df60e11b81529384019190915233602484015260448301849052516001600160a01b039091169163605be9be91606480830192600092919082900301818387803b15801561152157600080fd5b505af1158015611535573d6000803e3d6000fd5b5050336000908152601260205260408120818155600101555050505050565b6012602052600090815260409020805460019091015482565b60035461010090046001600160a01b031690565b60035461010090046001600160a01b0316331490565b600a5481565b60006115a7611581565b6115b057600080fd5b600f54600d546000906115c9908363ffffffff611a2416565b9050806115db57600092505050610a45565b60006116006115f0878463ffffffff611a2416565b610b99848863ffffffff611bdd16565b9050600061161883610b99868563ffffffff611bdd16565b905061162a848263ffffffff611bc816565b600f5561164f611640838363ffffffff611bc816565b600d549063ffffffff611bc816565b600d555095945050505050565b600d5490565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a41918590610afb908663ffffffff611bc816565b6116a6611581565b6116af57600080fd5b6116b7612163565b565b6000610a41338484611b90565b6116ce611581565b6116d757600080fd5b6001600160a01b038316611721576040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561171b573d6000803e3d6000fd5b50610a80565b826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561178157600080fd5b505af1158015611795573d6000803e3d6000fd5b505050506040513d60208110156117ab57600080fd5b5051610a80576040805162461bcd60e51b815260206004820152600c60248201526b111c985a5b8819985a5b195960a21b604482015290519081900360640190fd5b60006117f7611581565b61180057600080fd5b6000611817600d5484611a2490919063ffffffff16565b9050600061182f85610b99848963ffffffff611bdd16565b905061183c818584611ac5565b50949350505050565b600354600160a81b900460ff1615611895576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6003805460ff60a81b1916600160a81b1790556006839055600480546001600160a01b038085166001600160a01b03199283161790925560058054928416929091169190911790556118e68161216f565b5050670de0b6b3a7640000600a5550600e805460ff19166001179055565b6010546000908015610baa57610ba581610b996064600f54611bdd90919063ffffffff16565b6000611934611f5d565b9050600a5481101561198d576040805162461bcd60e51b815260206004820152601860248201527f546f6f20736d616c6c207265776172647320616d6f756e740000000000000000604482015290519081900360640190fd5b50565b60035460ff1681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600e5460ff1681565b60136020526000908152604090205481565b60116020526000908152604090205481565b6119f9611581565b611a0257600080fd5b61198d8161216f565b611a13611581565b611a1c57600080fd5b6116b76121e9565b600082820183811015611a3657600080fd5b9392505050565b6001600160a01b038216611a5057600080fd5b6001600160a01b038316611a6357600080fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6000611adb82610b99858763ffffffff611bdd16565b60085490915015611b1757611b14611b076064610b99600854610d34868a611bc890919063ffffffff16565b829063ffffffff611a2416565b90505b600754611b2a908263ffffffff611a2416565b6007556000611b3f858363ffffffff611bc816565b90506000611b4b610a8b565b90508015611b8857611b84611b7582610b99856a084595161401484a00000063ffffffff611bdd16565b600c549063ffffffff611a2416565b600c555b505050505050565b6040805162461bcd60e51b8152602060048201526008602482015267111a5cd8589b195960c21b604482015290519081900360640190fd5b600082821115611bd757600080fd5b50900390565b600082611bec57506000610a45565b82820282848281611bf957fe5b0414611a3657600080fd5b6000808211611c1257600080fd5b6000828481611c1d57fe5b04949350505050565b600080611c3283610cd5565b600c546001600160a01b038516600090815260136020526040902055915050919050565b6000611c606121f8565b600e5460ff16611cb0576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000611cba610b6c565b90506000611cd382610b9987606463ffffffff611bdd16565b905083811015611d1e576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b3360009081526012602052604090205415611d6f576040805162461bcd60e51b815260206004820152600c60248201526b13db99dbda5b99c8195e1a5d60a21b604482015290519081900360640190fd5b611d793382612239565b611da8611d916064610b99858563ffffffff611bdd16565b8681611d9957fe5b8791900663ffffffff611bc816565b600b54909550611dbe908663ffffffff611a2416565b600b5533600090815260116020526040902054611de1908663ffffffff611a2416565b33600090815260116020526040902055600d54611e04908663ffffffff611a2416565b600d5560055460065460408051629ff11560e81b8152600481019290925260248201889052516001600160a01b0390921691639ff115009160448082019260009290919082900301818387803b158015611e5d57600080fd5b505af1158015611e71573d6000803e3d6000fd5b5050600480546006546040805163c69d057360e01b815293840191909152336024840152604483018a905260648301869052516001600160a01b03909116935083925063c69d05739160848082019260009290919082900301818387803b158015611edb57600080fd5b505af1158015611eef573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611f3b57600080fd5b505af1158015611f4f573d6000803e3d6000fd5b509798975050505050505050565b600080611f6933611c26565b905080156120b7576005546006546040805163bc8756a960e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163bc8756a9916064808201926020929091908290030181600087803b158015611fcf57600080fd5b505af1158015611fe3573d6000803e3d6000fd5b505050506040513d6020811015611ff957600080fd5b5051612042576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163b7721d2d60e01b81529384019190915233602484015260448301849052516001600160a01b039091169163b7721d2d91606480830192600092919082900301818387803b15801561209e57600080fd5b505af11580156120b2573d6000803e3d6000fd5b505050505b905090565b6001600160a01b0382166120cf57600080fd5b6002546120e2908263ffffffff611bc816565b6002556001600160a01b03821660009081526020819052604090205461210e908263ffffffff611bc816565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b6003805460ff19169055565b6001600160a01b03811661218257600080fd5b6003546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6003805460ff19166001179055565b60035460ff16156116b7576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6001600160a01b03821661224c57600080fd5b60025461225f908263ffffffff611a2416565b6002556001600160a01b03821660009081526020819052604090205461228b908263ffffffff611a2416565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3505056fe436f6d6d697373696f6e20726174652073686f756c6420626520696e2072616e6765206f6620302d313030436f6d6d697373696f6e20726174652075706461746520636f6f6c646f776e20706572696f64a265627a7a72315820c703b73bb3087f93cdf906f2c3e3f1200dbb08e6f35ab04ba97b5166f5abeec464736f6c63430005110032
Verified Source Code Partial Match
Compiler: v0.5.17+commit.d19bba13
EVM: istanbul
Optimization: Yes (200 runs)
ValidatorShare.sol 1565 lines
// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.5.2;
/**
* @title ERC20 interface
* @dev see https://eips.ethereum.org/EIPS/eip-20
*/
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.5.2;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on 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-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
// File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
pragma solidity ^0.5.2;
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://eips.ethereum.org/EIPS/eip-20
* Originally based on code by FirstBlood:
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
* compliant implementations may not do it.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return A uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
/**
* @dev Transfer token to a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* 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
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* Note that while this function emits an Approval event, this is not required as per the specification,
* and other compliant implementations may not emit the event.
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
/**
* @dev Transfer token for a specified addresses
* @param from The address to transfer from.
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0));
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param value The amount that will be created.
*/
function _mint(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param owner The address that owns the tokens.
* @param spender The address that will spend the tokens.
* @param value The number of tokens that can be spent.
*/
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0));
require(owner != address(0));
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* Emits an Approval event (reflecting the reduced allowance).
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
_burn(account, value);
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
}
}
// File: contracts/common/tokens/ERC20NonTransferable.sol
pragma solidity ^0.5.2;
contract ERC20NonTransferable is ERC20 {
function _transfer(
address from,
address to,
uint256 value
) internal {
revert("Disabled");
}
}
// File: contracts/common/governance/IGovernance.sol
pragma solidity ^0.5.2;
interface IGovernance {
function update(address target, bytes calldata data) external;
}
// File: contracts/common/governance/Governable.sol
pragma solidity ^0.5.2;
contract Governable {
IGovernance public governance;
constructor(address _governance) public {
governance = IGovernance(_governance);
}
modifier onlyGovernance() {
require(
msg.sender == address(governance),
"Only governance contract is authorized"
);
_;
}
}
// File: contracts/root/withdrawManager/IWithdrawManager.sol
pragma solidity ^0.5.2;
contract IWithdrawManager {
function createExitQueue(address token) external;
function verifyInclusion(
bytes calldata data,
uint8 offset,
bool verifyTxInclusion
) external view returns (uint256 age);
function addExitToQueue(
address exitor,
address childToken,
address rootToken,
uint256 exitAmountOrTokenId,
bytes32 txHash,
bool isRegularExit,
uint256 priority
) external;
function addInput(
uint256 exitId,
uint256 age,
address utxoOwner,
address token
) external;
function challengeExit(
uint256 exitId,
uint256 inputId,
bytes calldata challengeData,
address adjudicatorPredicate
) external;
}
// File: contracts/common/Registry.sol
pragma solidity ^0.5.2;
contract Registry is Governable {
// @todo hardcode constants
bytes32 private constant WETH_TOKEN = keccak256("wethToken");
bytes32 private constant DEPOSIT_MANAGER = keccak256("depositManager");
bytes32 private constant STAKE_MANAGER = keccak256("stakeManager");
bytes32 private constant VALIDATOR_SHARE = keccak256("validatorShare");
bytes32 private constant WITHDRAW_MANAGER = keccak256("withdrawManager");
bytes32 private constant CHILD_CHAIN = keccak256("childChain");
bytes32 private constant STATE_SENDER = keccak256("stateSender");
bytes32 private constant SLASHING_MANAGER = keccak256("slashingManager");
address public erc20Predicate;
address public erc721Predicate;
mapping(bytes32 => address) public contractMap;
mapping(address => address) public rootToChildToken;
mapping(address => address) public childToRootToken;
mapping(address => bool) public proofValidatorContracts;
mapping(address => bool) public isERC721;
enum Type {Invalid, ERC20, ERC721, Custom}
struct Predicate {
Type _type;
}
mapping(address => Predicate) public predicates;
event TokenMapped(address indexed rootToken, address indexed childToken);
event ProofValidatorAdded(address indexed validator, address indexed from);
event ProofValidatorRemoved(address indexed validator, address indexed from);
event PredicateAdded(address indexed predicate, address indexed from);
event PredicateRemoved(address indexed predicate, address indexed from);
event ContractMapUpdated(bytes32 indexed key, address indexed previousContract, address indexed newContract);
constructor(address _governance) public Governable(_governance) {}
function updateContractMap(bytes32 _key, address _address) external onlyGovernance {
emit ContractMapUpdated(_key, contractMap[_key], _address);
contractMap[_key] = _address;
}
/**
* @dev Map root token to child token
* @param _rootToken Token address on the root chain
* @param _childToken Token address on the child chain
* @param _isERC721 Is the token being mapped ERC721
*/
function mapToken(
address _rootToken,
address _childToken,
bool _isERC721
) external onlyGovernance {
require(_rootToken != address(0x0) && _childToken != address(0x0), "INVALID_TOKEN_ADDRESS");
rootToChildToken[_rootToken] = _childToken;
childToRootToken[_childToken] = _rootToken;
isERC721[_rootToken] = _isERC721;
IWithdrawManager(contractMap[WITHDRAW_MANAGER]).createExitQueue(_rootToken);
emit TokenMapped(_rootToken, _childToken);
}
function addErc20Predicate(address predicate) public onlyGovernance {
require(predicate != address(0x0), "Can not add null address as predicate");
erc20Predicate = predicate;
addPredicate(predicate, Type.ERC20);
}
function addErc721Predicate(address predicate) public onlyGovernance {
erc721Predicate = predicate;
addPredicate(predicate, Type.ERC721);
}
function addPredicate(address predicate, Type _type) public onlyGovernance {
require(predicates[predicate]._type == Type.Invalid, "Predicate already added");
predicates[predicate]._type = _type;
emit PredicateAdded(predicate, msg.sender);
}
function removePredicate(address predicate) public onlyGovernance {
require(predicates[predicate]._type != Type.Invalid, "Predicate does not exist");
delete predicates[predicate];
emit PredicateRemoved(predicate, msg.sender);
}
function getValidatorShareAddress() public view returns (address) {
return contractMap[VALIDATOR_SHARE];
}
function getWethTokenAddress() public view returns (address) {
return contractMap[WETH_TOKEN];
}
function getDepositManagerAddress() public view returns (address) {
return contractMap[DEPOSIT_MANAGER];
}
function getStakeManagerAddress() public view returns (address) {
return contractMap[STAKE_MANAGER];
}
function getSlashingManagerAddress() public view returns (address) {
return contractMap[SLASHING_MANAGER];
}
function getWithdrawManagerAddress() public view returns (address) {
return contractMap[WITHDRAW_MANAGER];
}
function getChildChainAndStateSender() public view returns (address, address) {
return (contractMap[CHILD_CHAIN], contractMap[STATE_SENDER]);
}
function isTokenMapped(address _token) public view returns (bool) {
return rootToChildToken[_token] != address(0x0);
}
function isTokenMappedAndIsErc721(address _token) public view returns (bool) {
require(isTokenMapped(_token), "TOKEN_NOT_MAPPED");
return isERC721[_token];
}
function isTokenMappedAndGetPredicate(address _token) public view returns (address) {
if (isTokenMappedAndIsErc721(_token)) {
return erc721Predicate;
}
return erc20Predicate;
}
function isChildTokenErc721(address childToken) public view returns (bool) {
address rootToken = childToRootToken[childToken];
require(rootToken != address(0x0), "Child token is not mapped");
return isERC721[rootToken];
}
}
// File: openzeppelin-solidity/contracts/ownership/Ownable.sol
pragma solidity ^0.5.2;
/**
* @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 private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor () internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @return the address of the owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
* @notice Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// File: contracts/staking/StakingInfo.sol
pragma solidity ^0.5.2;
// dummy interface to avoid cyclic dependency
contract IStakeManagerLocal {
enum Status {Inactive, Active, Locked, Unstaked}
struct Validator {
uint256 amount;
uint256 reward;
uint256 activationEpoch;
uint256 deactivationEpoch;
uint256 jailTime;
address signer;
address contractAddress;
Status status;
}
mapping(uint256 => Validator) public validators;
bytes32 public accountStateRoot;
uint256 public activeAmount; // delegation amount from validator contract
uint256 public validatorRewards;
function currentValidatorSetTotalStake() public view returns (uint256);
// signer to Validator mapping
function signerToValidator(address validatorAddress)
public
view
returns (uint256);
function isValidator(uint256 validatorId) public view returns (bool);
}
contract StakingInfo is Ownable {
using SafeMath for uint256;
mapping(uint256 => uint256) public validatorNonce;
/// @dev Emitted when validator stakes in '_stakeFor()' in StakeManager.
/// @param signer validator address.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param activationEpoch validator's first epoch as proposer.
/// @param amount staking amount.
/// @param total total staking amount.
/// @param signerPubkey public key of the validator
event Staked(
address indexed signer,
uint256 indexed validatorId,
uint256 nonce,
uint256 indexed activationEpoch,
uint256 amount,
uint256 total,
bytes signerPubkey
);
/// @dev Emitted when validator unstakes in 'unstakeClaim()'
/// @param user address of the validator.
/// @param validatorId unique integer to identify a validator.
/// @param amount staking amount.
/// @param total total staking amount.
event Unstaked(
address indexed user,
uint256 indexed validatorId,
uint256 amount,
uint256 total
);
/// @dev Emitted when validator unstakes in '_unstake()'.
/// @param user address of the validator.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param deactivationEpoch last epoch for validator.
/// @param amount staking amount.
event UnstakeInit(
address indexed user,
uint256 indexed validatorId,
uint256 nonce,
uint256 deactivationEpoch,
uint256 indexed amount
);
/// @dev Emitted when the validator public key is updated in 'updateSigner()'.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param oldSigner old address of the validator.
/// @param newSigner new address of the validator.
/// @param signerPubkey public key of the validator.
event SignerChange(
uint256 indexed validatorId,
uint256 nonce,
address indexed oldSigner,
address indexed newSigner,
bytes signerPubkey
);
event Restaked(uint256 indexed validatorId, uint256 amount, uint256 total);
event Jailed(
uint256 indexed validatorId,
uint256 indexed exitEpoch,
address indexed signer
);
event UnJailed(uint256 indexed validatorId, address indexed signer);
event Slashed(uint256 indexed nonce, uint256 indexed amount);
event ThresholdChange(uint256 newThreshold, uint256 oldThreshold);
event DynastyValueChange(uint256 newDynasty, uint256 oldDynasty);
event ProposerBonusChange(
uint256 newProposerBonus,
uint256 oldProposerBonus
);
event RewardUpdate(uint256 newReward, uint256 oldReward);
/// @dev Emitted when validator confirms the auction bid and at the time of restaking in confirmAuctionBid() and restake().
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param newAmount the updated stake amount.
event StakeUpdate(
uint256 indexed validatorId,
uint256 indexed nonce,
uint256 indexed newAmount
);
event ClaimRewards(
uint256 indexed validatorId,
uint256 indexed amount,
uint256 indexed totalAmount
);
event StartAuction(
uint256 indexed validatorId,
uint256 indexed amount,
uint256 indexed auctionAmount
);
event ConfirmAuction(
uint256 indexed newValidatorId,
uint256 indexed oldValidatorId,
uint256 indexed amount
);
event TopUpFee(address indexed user, uint256 indexed fee);
event ClaimFee(address indexed user, uint256 indexed fee);
// Delegator events
event ShareMinted(
uint256 indexed validatorId,
address indexed user,
uint256 indexed amount,
uint256 tokens
);
event ShareBurned(
uint256 indexed validatorId,
address indexed user,
uint256 indexed amount,
uint256 tokens
);
event DelegatorClaimedRewards(
uint256 indexed validatorId,
address indexed user,
uint256 indexed rewards
);
event DelegatorRestaked(
uint256 indexed validatorId,
address indexed user,
uint256 indexed totalStaked
);
event DelegatorUnstaked(
uint256 indexed validatorId,
address indexed user,
uint256 amount
);
event UpdateCommissionRate(
uint256 indexed validatorId,
uint256 indexed newCommissionRate,
uint256 indexed oldCommissionRate
);
Registry public registry;
modifier onlyValidatorContract(uint256 validatorId) {
address _contract;
(, , , , , , _contract, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
require(_contract == msg.sender,
"Invalid sender, not validator");
_;
}
modifier StakeManagerOrValidatorContract(uint256 validatorId) {
address _contract;
address _stakeManager = registry.getStakeManagerAddress();
(, , , , , , _contract, ) = IStakeManagerLocal(_stakeManager).validators(
validatorId
);
require(_contract == msg.sender || _stakeManager == msg.sender,
"Invalid sender, not stake manager or validator contract");
_;
}
modifier onlyStakeManager() {
require(registry.getStakeManagerAddress() == msg.sender,
"Invalid sender, not stake manager");
_;
}
modifier onlySlashingManager() {
require(registry.getSlashingManagerAddress() == msg.sender,
"Invalid sender, not slashing manager");
_;
}
constructor(address _registry) public {
registry = Registry(_registry);
}
function updateNonce(
uint256[] calldata validatorIds,
uint256[] calldata nonces
) external onlyOwner {
require(validatorIds.length == nonces.length, "args length mismatch");
for (uint256 i = 0; i < validatorIds.length; ++i) {
validatorNonce[validatorIds[i]] = nonces[i];
}
}
function logStaked(
address signer,
bytes memory signerPubkey,
uint256 validatorId,
uint256 activationEpoch,
uint256 amount,
uint256 total
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit Staked(
signer,
validatorId,
validatorNonce[validatorId],
activationEpoch,
amount,
total,
signerPubkey
);
}
function logUnstaked(
address user,
uint256 validatorId,
uint256 amount,
uint256 total
) public onlyStakeManager {
emit Unstaked(user, validatorId, amount, total);
}
function logUnstakeInit(
address user,
uint256 validatorId,
uint256 deactivationEpoch,
uint256 amount
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit UnstakeInit(
user,
validatorId,
validatorNonce[validatorId],
deactivationEpoch,
amount
);
}
function logSignerChange(
uint256 validatorId,
address oldSigner,
address newSigner,
bytes memory signerPubkey
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit SignerChange(
validatorId,
validatorNonce[validatorId],
oldSigner,
newSigner,
signerPubkey
);
}
function logRestaked(uint256 validatorId, uint256 amount, uint256 total)
public
onlyStakeManager
{
emit Restaked(validatorId, amount, total);
}
function logJailed(uint256 validatorId, uint256 exitEpoch, address signer)
public
onlyStakeManager
{
emit Jailed(validatorId, exitEpoch, signer);
}
function logUnjailed(uint256 validatorId, address signer)
public
onlyStakeManager
{
emit UnJailed(validatorId, signer);
}
function logSlashed(uint256 nonce, uint256 amount)
public
onlySlashingManager
{
emit Slashed(nonce, amount);
}
function logThresholdChange(uint256 newThreshold, uint256 oldThreshold)
public
onlyStakeManager
{
emit ThresholdChange(newThreshold, oldThreshold);
}
function logDynastyValueChange(uint256 newDynasty, uint256 oldDynasty)
public
onlyStakeManager
{
emit DynastyValueChange(newDynasty, oldDynasty);
}
function logProposerBonusChange(
uint256 newProposerBonus,
uint256 oldProposerBonus
) public onlyStakeManager {
emit ProposerBonusChange(newProposerBonus, oldProposerBonus);
}
function logRewardUpdate(uint256 newReward, uint256 oldReward)
public
onlyStakeManager
{
emit RewardUpdate(newReward, oldReward);
}
function logStakeUpdate(uint256 validatorId)
public
StakeManagerOrValidatorContract(validatorId)
{
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit StakeUpdate(
validatorId,
validatorNonce[validatorId],
totalValidatorStake(validatorId)
);
}
function logClaimRewards(
uint256 validatorId,
uint256 amount,
uint256 totalAmount
) public onlyStakeManager {
emit ClaimRewards(validatorId, amount, totalAmount);
}
function logStartAuction(
uint256 validatorId,
uint256 amount,
uint256 auctionAmount
) public onlyStakeManager {
emit StartAuction(validatorId, amount, auctionAmount);
}
function logConfirmAuction(
uint256 newValidatorId,
uint256 oldValidatorId,
uint256 amount
) public onlyStakeManager {
emit ConfirmAuction(newValidatorId, oldValidatorId, amount);
}
function logTopUpFee(address user, uint256 fee) public onlyStakeManager {
emit TopUpFee(user, fee);
}
function logClaimFee(address user, uint256 fee) public onlyStakeManager {
emit ClaimFee(user, fee);
}
function getStakerDetails(uint256 validatorId)
public
view
returns (
uint256 amount,
uint256 reward,
uint256 activationEpoch,
uint256 deactivationEpoch,
address signer,
uint256 _status
)
{
IStakeManagerLocal stakeManager = IStakeManagerLocal(
registry.getStakeManagerAddress()
);
address _contract;
IStakeManagerLocal.Status status;
(
amount,
reward,
activationEpoch,
deactivationEpoch,
,
signer,
_contract,
status
) = stakeManager.validators(validatorId);
_status = uint256(status);
if (_contract != address(0x0)) {
reward += IStakeManagerLocal(_contract).validatorRewards();
}
}
function totalValidatorStake(uint256 validatorId)
public
view
returns (uint256 validatorStake)
{
address contractAddress;
(validatorStake, , , , , , contractAddress, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
if (contractAddress != address(0x0)) {
validatorStake += IStakeManagerLocal(contractAddress).activeAmount();
}
}
function getAccountStateRoot()
public
view
returns (bytes32 accountStateRoot)
{
accountStateRoot = IStakeManagerLocal(registry.getStakeManagerAddress())
.accountStateRoot();
}
function getValidatorContractAddress(uint256 validatorId)
public
view
returns (address ValidatorContract)
{
(, , , , , , ValidatorContract, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
}
// validator Share contract logging func
function logShareMinted(
uint256 validatorId,
address user,
uint256 amount,
uint256 tokens
) public onlyValidatorContract(validatorId) {
emit ShareMinted(validatorId, user, amount, tokens);
}
function logShareBurned(
uint256 validatorId,
address user,
uint256 amount,
uint256 tokens
) public onlyValidatorContract(validatorId) {
emit ShareBurned(validatorId, user, amount, tokens);
}
function logDelegatorClaimRewards(
uint256 validatorId,
address user,
uint256 rewards
) public onlyValidatorContract(validatorId) {
emit DelegatorClaimedRewards(validatorId, user, rewards);
}
function logDelegatorRestaked(
uint256 validatorId,
address user,
uint256 totalStaked
) public onlyValidatorContract(validatorId) {
emit DelegatorRestaked(validatorId, user, totalStaked);
}
function logDelegatorUnstaked(uint256 validatorId, address user, uint256 amount)
public
onlyValidatorContract(validatorId)
{
emit DelegatorUnstaked(validatorId, user, amount);
}
function logUpdateCommissionRate(
uint256 validatorId,
uint256 newCommissionRate,
uint256 oldCommissionRate
) public onlyValidatorContract(validatorId) {
emit UpdateCommissionRate(
validatorId,
newCommissionRate,
oldCommissionRate
);
}
}
// File: contracts/common/mixin/Lockable.sol
pragma solidity ^0.5.2;
contract Lockable {
bool public locked;
modifier onlyWhenUnlocked() {
_assertUnlocked();
_;
}
function _assertUnlocked() private view {
require(!locked, "locked");
}
function lock() public {
locked = true;
}
function unlock() public {
locked = false;
}
}
// File: contracts/common/mixin/OwnableLockable.sol
pragma solidity ^0.5.2;
contract OwnableLockable is Lockable, Ownable {
function lock() public onlyOwner {
super.lock();
}
function unlock() public onlyOwner {
super.unlock();
}
}
// File: contracts/staking/stakeManager/IStakeManager.sol
pragma solidity ^0.5.2;
contract IStakeManager {
// validator replacement
function startAuction(
uint256 validatorId,
uint256 amount,
bool acceptDelegation,
bytes calldata signerPubkey
) external;
function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) external;
function transferFunds(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool);
function delegationDeposit(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool);
function stake(
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) external;
function unstake(uint256 validatorId) external;
function totalStakedFor(address addr) external view returns (uint256);
function stakeFor(
address user,
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes memory signerPubkey
) public;
function checkSignatures(
uint256 blockInterval,
bytes32 voteHash,
bytes32 stateRoot,
address proposer,
bytes memory sigs
) public returns (uint256);
function updateValidatorState(uint256 validatorId, int256 amount) public;
function ownerOf(uint256 tokenId) public view returns (address);
function slash(bytes memory slashingInfoList) public returns (uint256);
function validatorStake(uint256 validatorId) public view returns (uint256);
function epoch() public view returns (uint256);
function withdrawalDelay() public view returns (uint256);
}
// File: contracts/staking/validatorShare/IValidatorShare.sol
pragma solidity ^0.5.2;
// note this contract interface is only for stakeManager use
contract IValidatorShare {
function withdrawRewardsValidator() external returns (uint256);
function addProposerBonus(uint256 _rewards, uint256 valStake) public;
function withdrawRewards() public;
function unstakeClaimTokens() public;
function getLiquidRewards(address user) public view returns (uint256);
function getActiveAmount() external view returns (uint256);
function owner() public view returns (address);
function restake() public;
function updateRewards(
uint256 _reward,
uint256 _totalStake,
uint256 validatorStake
) external returns (uint256);
function unlockContract() external returns (uint256);
function lockContract() external returns (uint256);
function drain(
address token,
address payable destination,
uint256 amount
) external;
function slash(uint256 valPow, uint256 totalAmountToSlash) external returns (uint256);
function updateDelegation(bool delegation) external;
}
// File: contracts/common/mixin/Initializable.sol
pragma solidity ^0.5.2;
contract Initializable {
bool inited = false;
modifier initializer() {
require(!inited, "already inited");
inited = true;
_;
}
}
// File: contracts/staking/validatorShare/ValidatorShare.sol
pragma solidity ^0.5.2;
contract ValidatorShare is IValidatorShare, ERC20NonTransferable, OwnableLockable, Initializable {
struct Delegator {
uint256 shares;
uint256 withdrawEpoch;
}
uint256 constant EXCHANGE_RATE_PRECISION = 100;
uint256 constant MAX_COMMISION_RATE = 100;
uint256 constant REWARD_PRECISION = 10**25;
StakingInfo public stakingLogger;
IStakeManager public stakeManager;
uint256 public validatorId;
uint256 public validatorRewards;
uint256 public commissionRate;
//last checkpoint where validator updated commission rate
uint256 public lastCommissionUpdate;
uint256 public minAmount = 10**18;
uint256 public totalStake;
uint256 public rewardPerShare;
uint256 public activeAmount;
bool public delegation = true;
uint256 public withdrawPool;
uint256 public withdrawShares;
mapping(address => uint256) public amountStaked;
mapping(address => Delegator) public delegators;
mapping(address => uint256) public initalRewardPerShare;
modifier onlyValidator() {
require(stakeManager.ownerOf(validatorId) == msg.sender, "not validator");
_;
}
// onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address
function initialize(uint256 _validatorId, address _stakingLogger, address _stakeManager) external initializer {
validatorId = _validatorId;
stakingLogger = StakingInfo(_stakingLogger);
stakeManager = IStakeManager(_stakeManager);
_transferOwnership(_stakeManager);
minAmount = 10**18;
delegation = true;
}
function updateCommissionRate(uint256 newCommissionRate) external onlyValidator {
uint256 epoch = stakeManager.epoch();
uint256 _lastCommissionUpdate = lastCommissionUpdate;
require( // withdrawalDelay == dynasty
(_lastCommissionUpdate.add(stakeManager.withdrawalDelay()) <= epoch) || _lastCommissionUpdate == 0, // For initial setting of commission rate
"Commission rate update cooldown period"
);
require(newCommissionRate <= MAX_COMMISION_RATE, "Commission rate should be in range of 0-100");
stakingLogger.logUpdateCommissionRate(validatorId, newCommissionRate, commissionRate);
commissionRate = newCommissionRate;
lastCommissionUpdate = epoch;
}
function updateRewards(uint256 reward, uint256 checkpointStakePower, uint256 validatorStake)
external
onlyOwner
returns (uint256)
{
/**
restaking is simply buying more shares of pool
but those needs to be nonswapable/transferrable(to prevent https://en.wikipedia.org/wiki/Tragedy_of_the_commons)
- calculate rewards for validator stake + delgation
- keep the validator rewards aside
- take the commission out
- add rewards to pool rewards
- returns total active stake for validator
*/
uint256 combinedStakePower = validatorStake.add(activeAmount); // validator + delegation stake power
uint256 rewards = combinedStakePower.mul(reward).div(checkpointStakePower);
_updateRewards(rewards, validatorStake, combinedStakePower);
return combinedStakePower;
}
function addProposerBonus(uint256 rewards, uint256 validatorStake) public onlyOwner {
uint256 combinedStakePower = validatorStake.add(activeAmount);
_updateRewards(rewards, validatorStake, combinedStakePower);
}
function _updateRewards(uint256 rewards, uint256 validatorStake, uint256 combinedStakePower) internal {
uint256 _validatorRewards = validatorStake.mul(rewards).div(combinedStakePower);
// add validator commission from delegation rewards
if (commissionRate > 0) {
_validatorRewards = _validatorRewards.add(
rewards.sub(_validatorRewards).mul(commissionRate).div(MAX_COMMISION_RATE)
);
}
validatorRewards = validatorRewards.add(_validatorRewards);
uint256 delegatorsRewards = rewards.sub(_validatorRewards);
uint256 totalShares = totalSupply();
if (totalShares > 0) {
rewardPerShare = rewardPerShare.add(
delegatorsRewards.mul(REWARD_PRECISION).div(totalShares)
);
}
}
function withdrawRewardsValidator() external onlyOwner returns (uint256) {
uint256 _validatorRewards = validatorRewards;
validatorRewards = 0;
return _validatorRewards;
}
function exchangeRate() public view returns (uint256) {
uint256 totalShares = totalSupply();
return
totalShares == 0
? EXCHANGE_RATE_PRECISION
: activeAmount.mul(EXCHANGE_RATE_PRECISION).div(totalShares);
}
function withdrawExchangeRate() public view returns (uint256) {
uint256 _withdrawShares = withdrawShares;
return
_withdrawShares == 0
? EXCHANGE_RATE_PRECISION
: withdrawPool.mul(EXCHANGE_RATE_PRECISION).div(_withdrawShares);
}
function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public {
_withdrawAndTransferReward();
uint256 amountToDeposit = _buyShares(_amount, _minSharesToMint);
require(stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), "deposit failed");
}
function restake() public {
uint256 liquidReward = _withdrawReward(msg.sender);
require(liquidReward >= minAmount, "Too small rewards to restake");
_buyShares(liquidReward, 0);
stakingLogger.logDelegatorRestaked(validatorId, msg.sender, amountStaked[msg.sender]);
}
function _buyShares(uint256 _amount, uint256 _minSharesToMint) private onlyWhenUnlocked returns(uint256) {
require(delegation, "Delegation is disabled");
uint256 rate = exchangeRate();
uint256 shares = _amount.mul(EXCHANGE_RATE_PRECISION).div(rate);
require(shares >= _minSharesToMint, "Too much slippage");
require(delegators[msg.sender].shares == 0, "Ongoing exit");
_mint(msg.sender, shares);
_amount = _amount.sub(_amount % rate.mul(shares).div(EXCHANGE_RATE_PRECISION));
totalStake = totalStake.add(_amount);
amountStaked[msg.sender] = amountStaked[msg.sender].add(_amount);
activeAmount = activeAmount.add(_amount);
stakeManager.updateValidatorState(validatorId, int256(_amount));
StakingInfo logger = stakingLogger;
logger.logShareMinted(validatorId, msg.sender, _amount, shares);
logger.logStakeUpdate(validatorId);
return _amount;
}
function sellVoucher(uint256 _minClaimAmount) public {
uint256 shares = balanceOf(msg.sender);
require(shares > 0, "Zero balance");
uint256 rate = exchangeRate();
uint256 _amount = rate.mul(shares).div(EXCHANGE_RATE_PRECISION);
require(_amount >= _minClaimAmount, "Too much slippage");
_withdrawAndTransferReward();
_burn(msg.sender, shares);
stakeManager.updateValidatorState(validatorId, -int256(_amount));
activeAmount = activeAmount.sub(_amount);
uint256 _withdrawPoolShare = _amount.mul(EXCHANGE_RATE_PRECISION).div(withdrawExchangeRate());
withdrawPool = withdrawPool.add(_amount);
withdrawShares = withdrawShares.add(_withdrawPoolShare);
delegators[msg.sender] = Delegator({shares: _withdrawPoolShare, withdrawEpoch: stakeManager.epoch()});
amountStaked[msg.sender] = 0;
StakingInfo logger = stakingLogger;
logger.logShareBurned(validatorId, msg.sender, _amount, shares);
logger.logStakeUpdate(validatorId);
}
function _withdrawReward(address user) private returns(uint256) {
uint256 liquidRewards = getLiquidRewards(user);
initalRewardPerShare[user] = rewardPerShare;
return liquidRewards;
}
function _withdrawAndTransferReward() private returns(uint256) {
uint256 liquidRewards = _withdrawReward(msg.sender);
if (liquidRewards > 0) {
require(stakeManager.transferFunds(validatorId, liquidRewards, msg.sender), "Insufficent rewards");
stakingLogger.logDelegatorClaimRewards(validatorId, msg.sender, liquidRewards);
}
return liquidRewards;
}
function withdrawRewards() public {
uint256 rewards = _withdrawAndTransferReward();
require(rewards >= minAmount, "Too small rewards amount");
}
function getLiquidRewards(address user) public view returns (uint256) {
uint256 shares = balanceOf(user);
if (shares == 0) {
return 0;
}
return rewardPerShare.sub(initalRewardPerShare[user]).mul(shares).div(REWARD_PRECISION);
}
function unstakeClaimTokens() public {
Delegator storage delegator = delegators[msg.sender];
uint256 shares = delegator.shares;
require(
delegator.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0,
"Incomplete withdrawal period"
);
uint256 _amount = withdrawExchangeRate().mul(shares).div(EXCHANGE_RATE_PRECISION);
withdrawShares = withdrawShares.sub(shares);
withdrawPool = withdrawPool.sub(_amount);
totalStake = totalStake.sub(_amount);
require(stakeManager.transferFunds(validatorId, _amount, msg.sender), "Insufficent rewards");
stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, _amount);
delete delegators[msg.sender];
}
func...
// [truncated — 51623 bytes total]
Read Contract
activeAmount 0x3a09bf44 → uint256
allowance 0xdd62ed3e → uint256
amountStaked 0xef40a670 → uint256
balanceOf 0x70a08231 → uint256
commissionRate 0x5ea1d6f8 → uint256
delegation 0xdf5cf723 → bool
delegators 0x8d23fc61 → uint256, uint256
exchangeRate 0x3ba0b9a9 → uint256
getActiveAmount 0xa446c2db → uint256
getLiquidRewards 0x676e5550 → uint256
initalRewardPerShare 0xe4cd1aec → uint256
isOwner 0x8f32d59b → bool
lastCommissionUpdate 0x0d58a5f3 → uint256
locked 0xcf309012 → bool
minAmount 0x9b2cb5d8 → uint256
owner 0x8da5cb5b → address
rewardPerShare 0x446a2ec8 → uint256
stakeManager 0x7542ff95 → address
stakingLogger 0x3d94eb05 → address
totalStake 0x8b0e9f3f → uint256
totalSupply 0x18160ddd → uint256
validatorId 0x5c5f7dae → uint256
validatorRewards 0x5d1e3616 → uint256
withdrawExchangeRate 0xbfb18f29 → uint256
withdrawPool 0x5c42c733 → uint256
withdrawShares 0x8d086da4 → uint256
Write Contract 24 functions
These functions modify contract state and require a wallet transaction to execute.
addProposerBonus 0x0d331908
uint256 rewards
uint256 validatorStake
approve 0x095ea7b3
address spender
uint256 value
returns: bool
buyVoucher 0x6ab15071
uint256 _amount
uint256 _minSharesToMint
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
drain 0xabf59fc9
address token
address destination
uint256 amount
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
initialize 0xb4988fd0
uint256 _validatorId
address _stakingLogger
address _stakeManager
lock 0xf83d08ba
No parameters
lockContract 0x753868e3
No parameters
returns: uint256
renounceOwnership 0x715018a6
No parameters
restake 0x4f91440d
No parameters
sellVoucher 0x6c751897
uint256 _minClaimAmount
slash 0xa22a6428
uint256 valPow
uint256 totalAmountToSlash
returns: uint256
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferOwnership 0xf2fde38b
address newOwner
unlock 0xa69df4b5
No parameters
unlockContract 0x22f0f2f9
No parameters
returns: uint256
unstakeClaimTokens 0x8d16a14a
No parameters
updateCommissionRate 0x00fa3d50
uint256 newCommissionRate
updateDelegation 0x7ba8c820
bool _delegation
updateRewards 0xb37f2590
uint256 reward
uint256 checkpointStakePower
uint256 validatorStake
returns: uint256
withdrawRewards 0xc7b8981c
No parameters
withdrawRewardsValidator 0x32ba2e53
No parameters
returns: uint256
Recent Transactions
This address has 1 on-chain transactions, but only 1.4% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →