Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x5Fa19F612dfd39e6754Bb2E8300E681d1C589Dd4
Balance 0 ETH
Nonce 1
Code Size 23427 bytes
Indexed Transactions 0 (1 on-chain, 1.1% indexed)
External Etherscan · Sourcify

Contract Bytecode

23427 bytes
0x608060405234801561001057600080fd5b50600436106102f15760003560e01c806361d027b31161019d578063a230c524116100e9578063e4ebdfa5116100a2578063ed06d4e21161007c578063ed06d4e21461132e578063f525cb68146113b4578063f96e9ea1146113d2578063fa8f382a14611434576102f1565b8063e4ebdfa5146111ec578063eb76595514611268578063ec7d7199146112d6576102f1565b8063a230c52414610fec578063baff15ce14611048578063c251adeb146110b6578063ce110e4b14611100578063ddd5e1b214611158578063e07dbfbd146111a6576102f1565b806378a45a241161015657806387e2662e1161013057806387e2662e14610e965780638b5e608b14610ef2578063973628f614610f4a578063a19d164614610f68576102f1565b806378a45a2414610dd85780637f2277b414610df6578063845696b414610e52576102f1565b806361d027b314610c1457806369b3039814610c5e5780636ea056a914610cb45780637048027514610d0257806371586b1f14610d4657806375829def14610d94576102f1565b8063322e26041161025c5780634445c1ea116102155780634a5cab98116101ef5780634a5cab9814610a885780634dd85b5e14610ad6578063522cff2514610b385780635976c67c14610b90576102f1565b80634445c1ea1461093657806344d3d337146109a457806344d7e45514610a06576102f1565b8063322e26041461067057806332bc68be146106d25780633d23e24a146107405780633e66034f146107b8578063429d7e8f1461083a578063436f80be146108c8576102f1565b8063282d3fdf116102ae578063282d3fdf146104b45780632b7832b3146105025780632f6c493c14610520578063306faf4a1461056457806331405c03146105a85780633224e2f21461060e576102f1565b80630382ad26146102f657806311aee3801461035857806316d534711461037657806324d7806c146103d2578063265121601461042e57806326b8052914610472575b600080fd5b6103426004803603604081101561030c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506114c2565b6040518082815260200191505060405180910390f35b6103606115b1565b6040518082815260200191505060405180910390f35b6103b86004803603602081101561038c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115be565b604051808215151515815260200191505060405180910390f35b610414600480360360208110156103e857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115de565b604051808215151515815260200191505060405180910390f35b6104706004803603602081101561044457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115fe565b005b61049e6004803603602081101561048857600080fd5b81019080803590602001909291905050506116e8565b6040518082815260200191505060405180910390f35b610500600480360360408110156104ca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611700565b005b61050a611f4e565b6040518082815260200191505060405180910390f35b6105626004803603602081101561053657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f5b565b005b6105a66004803603602081101561057a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612416565b005b6105f4600480360360408110156105be57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612530565b604051808215151515815260200191505060405180910390f35b61066e6004803603608081101561062457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061255f565b005b6106bc6004803603604081101561068657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a3b565b6040518082815260200191505060405180910390f35b6106fe600480360360208110156106e857600080fd5b8101908080359060200190929190505050612a60565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107a26004803603604081101561075657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a9c565b6040518082815260200191505060405180910390f35b610824600480360360608110156107ce57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ac1565b6040518082815260200191505060405180910390f35b6108c66004803603608081101561085057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612c2b565b005b6108f4600480360360208110156108de57600080fd5b8101908080359060200190929190505050612f42565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109626004803603602081101561094c57600080fd5b8101908080359060200190929190505050612f7e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109f0600480360360408110156109ba57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612fba565b6040518082815260200191505060405180910390f35b610a7260048036036060811015610a1c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612fdf565b6040518082815260200191505060405180910390f35b610ad460048036036040811015610a9e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613011565b005b610b2260048036036040811015610aec57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506130f3565b6040518082815260200191505060405180910390f35b610b7a60048036036020811015610b4e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613118565b6040518082815260200191505060405180910390f35b610bd260048036036020811015610ba657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613130565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c1c613163565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c9e60048036036060811015610c7457600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050613189565b6040518082815260200191505060405180910390f35b610d0060048036036040811015610cca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506131b9565b005b610d4460048036036020811015610d1857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506133d2565b005b610d9260048036036040811015610d5c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061364e565b005b610dd660048036036020811015610daa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506139d4565b005b610de0613ca8565b6040518082815260200191505060405180910390f35b610e3860048036036020811015610e0c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613cb5565b604051808215151515815260200191505060405180910390f35b610e9460048036036020811015610e6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613cd5565b005b610ed860048036036020811015610eac57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614257565b604051808215151515815260200191505060405180910390f35b610f3460048036036020811015610f0857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614277565b6040518082815260200191505060405180910390f35b610f5261428f565b6040518082815260200191505060405180910390f35b610faa60048036036020811015610f7e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614295565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61102e6004803603602081101561100257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506142c8565b604051808215151515815260200191505060405180910390f35b6110b46004803603606081101561105e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506142e8565b005b6110be6147ed565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6111426004803603602081101561111657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614813565b6040518082815260200191505060405180910390f35b6111a46004803603604081101561116e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061482b565b005b6111d2600480360360208110156111bc57600080fd5b8101908080359060200190929190505050614e46565b604051808215151515815260200191505060405180910390f35b61124e6004803603604081101561120257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614e66565b604051808215151515815260200191505060405180910390f35b6112946004803603602081101561127e57600080fd5b8101908080359060200190929190505050614e95565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61132c600480360360608110156112ec57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050614ed1565b005b61139a6004803603606081101561134457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614fbf565b604051808215151515815260200191505060405180910390f35b6113bc614ffb565b6040518082815260200191505060405180910390f35b61141e600480360360408110156113e857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615008565b6040518082815260200191505060405180910390f35b6114806004803603604081101561144a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061502d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600080600090505b601760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548110156115a7576000601860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811061155d57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050611595858583612ac1565b830192505080806001019150506114ca565b5080905092915050565b6000600680549050905090565b600b6020528060005260406000206000915054906101000a900460ff1681565b60086020528060005260406000206000915054906101000a900460ff1681565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b6116c981600754613011565b6116df600160075461507890919063ffffffff16565b60078190555050565b600e6020528060005260406000206000915090505481565b60026000541415611779576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260008190555060011515600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514611847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4d757374206265206c697374656400000000000000000000000000000000000081525060200191505060405180910390fd5b601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611954576006339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166119fe576001600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b601a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611c5857611adf6001601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001601a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b158015611d1357600080fd5b505af1158015611d27573d6000803e3d6000fd5b505050506040513d6020811015611d3d57600080fd5b8101908080519060200190929190505050611dc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d757374207472616e736665720000000000000000000000000000000000000081525060200191505060405180910390fd5b611e4f81601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611eda338383615100565b6007548273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f26c1d455ed5e9a313ff262b6cd70a49110f54a2a68591881424ade0176624983846040518082815260200191505060405180910390a460016000819055505050565b6000600380549050905090565b60026000541415611fd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b60026000819055506000601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081116120d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d757374206861766520612062616c616e636520746f20636c61696d0000000081525060200191505060405180910390fd5b6000601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156121dc57600080fd5b505af11580156121f0573d6000803e3d6000fd5b505050506040513d602081101561220657600080fd5b8101908080519060200190929190505050612289576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d757374207472616e736665720000000000000000000000000000000000000081525060200191505060405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561230857600080fd5b505afa15801561231c573d6000803e3d6000fd5b505050506040513d602081101561233257600080fd5b810190808051906020019092919050505014156123a2576000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b6007548273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffc457b903eae2c3f6e2d259cccaae44e68f974c0c77dda2f7877aa4ed140d5c6846040518082815260200191505060405180910390a450600160008190555050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166124d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b601b6020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661261e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156126c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f41646472657373206d757374206e6f742062652030783000000000000000000081525060200191505060405180910390fd5b60016007540383101580156126d857506007548311155b61272d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615b2a6024913960400191505060405180910390fd5b6000612838600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156127ef57600080fd5b505afa158015612803573d6000803e3d6000fd5b505050506040513d602081101561281957600080fd5b81019080805190602001909291905050506152c590919063ffffffff16565b9050600081116128b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f416d6f756e74206d757374206265206e6f6e2d7a65726f00000000000000000081525060200191505060405180910390fd5b61290281600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506129a8816010600087815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b6010600086815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001600f600086815260200190815260200160002060006101000a81548160ff021916908315150217905550612a348482858561530f565b5050505050565b6012602052816000526040600020602052806000526040600020600091509150505481565b60048181548110612a6d57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6019602052816000526040600020602052806000526040600020600091509150505481565b6000806012600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000601c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006013600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811115612c1957612c12828285613189565b9350612c1e565b600093505b8393505050509392505050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612cea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612d8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d757374207061737320616464726573732076616c69646174696f6e0000000081525060200191505060405180910390fd5b600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612e42576005839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b612e4d8484836142e8565b81601560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f4e351dd0f3a8cc5682178a81d960be19d454f9fe874a9d4f0753caae5685900060405160405180910390a450505050565b60068181548110612f4f57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60038181548110612f8b57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6010602052816000526040600020602052806000526040600020600091509150505481565b601c60205282600052604060002060205281600052604060002060205280600052604060002060009250925050505481565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166130d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b600080905060006130df614ffb565b90506130ed8484848461255f565b50505050565b6011602052816000526040600020602052806000526040600020600091509150505481565b600c6020528060005260406000206000915090505481565b60156020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006131b0836131a2868561583990919063ffffffff16565b6158bf90919063ffffffff16565b90509392505050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16613278576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561332157600080fd5b505af1158015613335573d6000803e3d6000fd5b505050506040513d602081101561334b57600080fd5b81019080805190602001909291905050506133ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d757374207472616e736665720000000000000000000000000000000000000081525060200191505060405180910390fd5b5050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16613491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b60001515600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514801561351e5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613590576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d757374207061737320616464726573732076616c69646174696f6e0000000081525060200191505060405180910390fd5b6003819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661370d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b60006010600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006010600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061380a81600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152c590919063ffffffff16565b600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600f600085815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561392257600080fd5b505af1158015613936573d6000803e3d6000fd5b505050506040513d602081101561394c57600080fd5b81019080805190602001909291905050506139cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d757374207472616e736665720000000000000000000000000000000000000081525060200191505060405180910390fd5b505050565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16613a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b60001515600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515148015613b205750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613b92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d757374207061737320616464726573732076616c69646174696f6e0000000081525060200191505060405180910390fd5b6003819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000600580549050905090565b60096020528060005260406000206000915054906101000a900460ff1681565b60001515601b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060009054906101000a900460ff16151514613d91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615ab7602c913960400191505060405180910390fd5b60008090505b601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548110156141e8576000601860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110613e2a57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050613f4b601c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460136000600754815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152c590919063ffffffff16565b60136000600754815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000601960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905080601c60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061411b8160136000600754815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b60136000600754815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506007548273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f1c6cf7f4185192b90e5dbc6c1030559d3a499bc798a5fd775870659fe4e254c4846040518082815260200191505060405180910390a450508080600101915050613d97565b506001601b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600a6020528060005260406000206000915054906101000a900460ff1681565b600d6020528060005260406000206000915090505481565b60075481565b60146020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60166020528060005260406000206000915054906101000a900460ff1681565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166143a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156144325750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561446b5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b6144dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4d757374207061737320616464726573732076616c69646174696f6e0000000081525060200191505060405180910390fd5b600a81101580156144f057506103e88111155b614545576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ae36026913960400191505060405180910390fd5b600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166145fa576004839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6001600960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081601460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6f1e56c55b9479aaa7ee72e01aa069c9d9e1874fa8145a0d010c1ce91483df15846040518082815260200191505060405180910390a4505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60176020528060005260406000206000915090505481565b600260005414156148a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b600260008190555060001515601d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146149a3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180615a906027913960400191505060405180910390fd5b600f600083815260200190815260200160002060009054906101000a900460ff16614a36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f457261206d757374206265206f70656e6564000000000000000000000000000081525060200191505060405180910390fd5b6000614a4233846114c2565b90506000811115614d74576001601d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550614b56816010600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152c590919063ffffffff16565b6010600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550614bfc81600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546152c590919063ffffffff16565b600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015614cc657600080fd5b505af1158015614cda573d6000803e3d6000fd5b505050506040513d6020811015614cf057600080fd5b8101908080519060200190929190505050614d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d757374207472616e736665720000000000000000000000000000000000000081525060200191505060405180910390fd5b5b823373ffffffffffffffffffffffffffffffffffffffff167f0febf5fad8005f14b1cf04172c840311f6c94fe0e14e38087260ba190a357b32836040518082815260200191505060405180910390a360001515601b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060009054906101000a900460ff1615151415614e3957614e3833613cd5565b5b5060016000819055505050565b600f6020528060005260406000206000915054906101000a900460ff1681565b601a6020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b60058181548110614ea257fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16614f90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742062652041646d696e0000000000000000000000000000000000000081525060200191505060405180910390fd5b614f9e83600754848461255f565b614fb4600160075461507890919063ffffffff16565b600781905550505050565b601d602052826000526040600020602052816000526040600020602052806000526040600020600092509250509054906101000a900460ff1681565b6000600480549050905090565b6013602052816000526040600020602052806000526040600020600091509150505481565b6018602052816000526040600020818154811061504657fe5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000808284019050838110156150f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b80601c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600754815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055506152028160136000600754815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461507890919063ffffffff16565b60136000600754815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506007548273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f1c6cf7f4185192b90e5dbc6c1030559d3a499bc798a5fd775870659fe4e254c4846040518082815260200191505060405180910390a4505050565b600061530783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615909565b905092915050565b6000806000808590505b848110156155dc5760006004828154811061533057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156153ff5750600a60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156155ce5761541860018561507890919063ffffffff16565b93506000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600061555f606461555184600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231886040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561550857600080fd5b505afa15801561551c573d6000803e3d6000fd5b505050506040513d602081101561553257600080fd5b810190808051906020019092919050505061583990919063ffffffff16565b6158bf90919063ffffffff16565b9050615574818861507890919063ffffffff16565b965080601160008d815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505b508080600101915050615319565b5082600e60008981526020019081526020016000208190555060008590505b848110156157c05760006004828154811061561257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156156e15750600a60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156157b2576156fa60018461507890919063ffffffff16565b92506000601160008b815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061575c81878b613189565b601260008c815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b5080806001019150506155fb565b50863373ffffffffffffffffffffffffffffffffffffffff167fd7b022ad987606d8c29043f24a451ccffc5aa3a813994c086b6da216c3d8df348886868642604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a350505050505050565b60008083141561584c57600090506158b9565b600082840290508284828161585d57fe5b04146158b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615b096021913960400191505060405180910390fd5b809150505b92915050565b600061590183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506159c9565b905092915050565b60008383111582906159b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561597b578082015181840152602081019050615960565b50505050905090810190601f1680156159a85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008083118290615a75576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015615a3a578082015181840152602081019050615a1f565b50505050905090810190601f168015615a675780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581615a8157fe5b04905080915050939250505056fe526577617264206173736574206d757374206e6f742068617665206265656e20636c61696d65644d757374206e6f742068617665207265676973746572656420696e20746869732065726120616c72656164794d7573742062652067726561746572207468616e20302e312c206c657373207468616e203130536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774d7573742062652063757272656e74206f722070726576696f757320657261206f6e6c79a2646970667358221220523b33e2823930670089b7bf3a73590a67a8cf64cb5932041997a6bb5b4cd22064736f6c63430006080033

Verified Source Code Full Match

Compiler: v0.6.8+commit.0bbfe453 EVM: istanbul Optimization: No
rewards.sol 524 lines
//SPDX-License-Identifier: Unlicense
pragma solidity 0.6.8;

// ERC20 Interface
interface ERC20 {
    function transfer(address, uint256) external returns (bool);

    function transferFrom(
        address,
        address,
        uint256
    ) external returns (bool);

    function balanceOf(address account) external view returns (uint256);
}

library SafeMath {

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;
        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        return c;
    }
}

contract PerlinXRewards {
    using SafeMath for uint256;
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;
    uint256 private _status;

    address public PERL;
    address public treasury;

    address[] public arrayAdmins;
    address[] public arrayPerlinPools;
    address[] public arraySynths;
    address[] public arrayMembers;

    uint256 public currentEra;

    mapping(address => bool) public isAdmin; // Tracks admin status
    mapping(address => bool) public poolIsListed; // Tracks current listing status
    mapping(address => bool) public poolHasMembers; // Tracks current staking status
    mapping(address => bool) public poolWasListed; // Tracks if pool was ever listed
    mapping(address => uint256) public mapAsset_Rewards; // Maps rewards for each asset (PERL, BAL, UNI etc)
    mapping(address => uint256) public poolWeight; // Allows a reward weight to be applied; 100 = 1.0
    mapping(uint256 => uint256) public mapEra_Total; // Total PERL staked in each era
    mapping(uint256 => bool) public eraIsOpen; // Era is open of collecting rewards
    mapping(uint256 => mapping(address => uint256)) public mapEraAsset_Reward; // Reward allocated for era
    mapping(uint256 => mapping(address => uint256)) public mapEraPool_Balance; // Perls in each pool, per era
    mapping(uint256 => mapping(address => uint256)) public mapEraPool_Share; // Share of reward for each pool, per era
    mapping(uint256 => mapping(address => uint256)) public mapEraPool_Claims; // Total LP tokens locked for each pool, per era

    mapping(address => address) public mapPool_Asset; // Uniswap pools provide liquidity to non-PERL asset
    mapping(address => address) public mapSynth_EMP; // Synthetic Assets have a management contract

    mapping(address => bool) public isMember; // Is Member
    mapping(address => uint256) public mapMember_poolCount; // Total number of Pools member is in
    mapping(address => address[]) public mapMember_arrayPools; // Array of pools for member
    mapping(address => mapping(address => uint256))
        public mapMemberPool_Balance; // Member's balance in pool
    mapping(address => mapping(address => bool)) public mapMemberPool_Added; // Member's balance in pool
    mapping(address => mapping(uint256 => bool))
        public mapMemberEra_hasRegistered; // Member has registered
    mapping(address => mapping(uint256 => mapping(address => uint256)))
        public mapMemberEraPool_Claim; // Value of claim per pool, per era
    mapping(address => mapping(uint256 => mapping(address => bool)))
        public mapMemberEraAsset_hasClaimed; // Boolean claimed

    // Events
    event Snapshot(
        address indexed admin,
        uint256 indexed era,
        uint256 rewardForEra,
        uint256 perlTotal,
        uint256 validPoolCount,
        uint256 validMemberCount,
        uint256 date
    );
    event NewPool(
        address indexed admin,
        address indexed pool,
        address indexed asset,
        uint256 assetWeight
    );
    event NewSynth(
        address indexed pool,
        address indexed synth,
        address indexed expiringMultiParty
    );
    event MemberLocks(
        address indexed member,
        address indexed pool,
        uint256 amount,
        uint256 indexed currentEra
    );
    event MemberUnlocks(
        address indexed member,
        address indexed pool,
        uint256 balance,
        uint256 indexed currentEra
    );
    event MemberRegisters(
        address indexed member,
        address indexed pool,
        uint256 amount,
        uint256 indexed currentEra
    );
    event MemberClaims(address indexed member, uint256 indexed era, uint256 totalClaim);

    // Only Admin can execute
    modifier onlyAdmin() {
        require(isAdmin[msg.sender], "Must be Admin");
        _;
    }

    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;
        _;
        _status = _NOT_ENTERED;
    }

    constructor() public {
        arrayAdmins.push(msg.sender);
        isAdmin[msg.sender] = true;
        PERL = 0xeca82185adCE47f39c684352B0439f030f860318;
        treasury = 0x3F2a2c502E575f2fd4053c76f4E21623143518d8; 
        currentEra = 1;
        _status = _NOT_ENTERED;
    }

    //==============================ADMIN================================//

    // Lists a synth and its parent EMP address
    function listSynth(
        address pool,
        address synth,
        address emp,
        uint256 weight
    ) public onlyAdmin {
        require(emp != address(0), "Must pass address validation");
        if (!poolWasListed[pool]) {
            arraySynths.push(synth); // Add new synth
        }
        listPool(pool, synth, weight); // List like normal pool
        mapSynth_EMP[synth] = emp; // Maps the EMP contract for look-up
        emit NewSynth(pool, synth, emp);
    }

    // Lists a pool and its non-PERL asset (can work for Balance or Uniswap V2)
    // Use "100" to be a normal weight of "1.0"
    function listPool(
        address pool,
        address asset,
        uint256 weight
    ) public onlyAdmin {
        require(
            (asset != PERL) && (asset != address(0)) && (pool != address(0)),
            "Must pass address validation"
        );
        require(
            weight >= 10 && weight <= 1000,
            "Must be greater than 0.1, less than 10"
        );
        if (!poolWasListed[pool]) {
            arrayPerlinPools.push(pool);
        }
        poolIsListed[pool] = true; // Tracking listing
        poolWasListed[pool] = true; // Track if ever was listed
        poolWeight[pool] = weight; // Note: weight of 120 = 1.2
        mapPool_Asset[pool] = asset; // Map the pool to its non-perl asset
        emit NewPool(msg.sender, pool, asset, weight);
    }

    function delistPool(address pool) public onlyAdmin {
        poolIsListed[pool] = false;
    }

    // Quorum Action 1
    function addAdmin(address newAdmin) public onlyAdmin {
        require(
            (isAdmin[newAdmin] == false) && (newAdmin != address(0)),
            "Must pass address validation"
        );
        arrayAdmins.push(newAdmin);
        isAdmin[newAdmin] = true;
    }

    function transferAdmin(address newAdmin) public onlyAdmin {
        require(
            (isAdmin[newAdmin] == false) && (newAdmin != address(0)),
            "Must pass address validation"
        );
        arrayAdmins.push(newAdmin);
        isAdmin[msg.sender] = false;
        isAdmin[newAdmin] = true;
    }

    // Snapshot a new Era, allocating any new rewards found on the address, increment Era
    // Admin should send reward funds first
    function snapshot(address rewardAsset) public onlyAdmin {
        snapshotInEra(rewardAsset, currentEra); // Snapshots PERL balances
        currentEra = currentEra.add(1); // Increment the eraCount, so users can't register in a previous era.
    }

    // Snapshot a particular rewwardAsset, but don't increment Era (like Balancer Rewards)
    // Do this after snapshotPools()
    function snapshotInEra(address rewardAsset, uint256 era) public onlyAdmin {
        uint256 start = 0;
        uint256 end = poolCount();
        snapshotInEraWithOffset(rewardAsset, era, start, end);
    }

    // Snapshot with offset (in case runs out of gas)
    function snapshotWithOffset(
        address rewardAsset,
        uint256 start,
        uint256 end
    ) public onlyAdmin {
        snapshotInEraWithOffset(rewardAsset, currentEra, start, end); // Snapshots PERL balances
        currentEra = currentEra.add(1); // Increment the eraCount, so users can't register in a previous era.
    }

    // Snapshot a particular rewwardAsset, with offset
    function snapshotInEraWithOffset(
        address rewardAsset,
        uint256 era,
        uint256 start,
        uint256 end
    ) public onlyAdmin {
        require(rewardAsset != address(0), "Address must not be 0x0");
        require(
            (era >= currentEra - 1) && (era <= currentEra),
            "Must be current or previous era only"
        );
        uint256 amount = ERC20(rewardAsset).balanceOf(address(this)).sub(
            mapAsset_Rewards[rewardAsset]
        );
        require(amount > 0, "Amount must be non-zero");
        mapAsset_Rewards[rewardAsset] = mapAsset_Rewards[rewardAsset].add(
            amount
        );
        mapEraAsset_Reward[era][rewardAsset] = mapEraAsset_Reward[era][rewardAsset]
            .add(amount);
        eraIsOpen[era] = true;
        updateRewards(era, amount, start, end); // Snapshots PERL balances
    }

    // Note, due to EVM gas limits, poolCount should be less than 100 to do this before running out of gas
    function updateRewards(
        uint256 era,
        uint256 rewardForEra,
        uint256 start,
        uint256 end
    ) internal {
        // First snapshot balances of each pool
        uint256 perlTotal;
        uint256 validPoolCount;
        uint256 validMemberCount;
        for (uint256 i = start; i < end; i++) {
            address pool = arrayPerlinPools[i];
            if (poolIsListed[pool] && poolHasMembers[pool]) {
                validPoolCount = validPoolCount.add(1);
                uint256 weight = poolWeight[pool];
                uint256 weightedBalance = (
                    ERC20(PERL).balanceOf(pool).mul(weight)).div(100); // (depth * weight) / 100
                perlTotal = perlTotal.add(weightedBalance);
                mapEraPool_Balance[era][pool] = weightedBalance;
            }
        }
        mapEra_Total[era] = perlTotal;
        // Then snapshot share of the reward for the era
        for (uint256 i = start; i < end; i++) {
            address pool = arrayPerlinPools[i];
            if (poolIsListed[pool] && poolHasMembers[pool]) {
                validMemberCount = validMemberCount.add(1);
                uint256 part = mapEraPool_Balance[era][pool];
                mapEraPool_Share[era][pool] = getShare(
                    part,
                    perlTotal,
                    rewardForEra
                );
            }
        }
        emit Snapshot(
            msg.sender,
            era,
            rewardForEra,
            perlTotal,
            validPoolCount,
            validMemberCount,
            now
        );
    }

    // Quorum Action
    // Remove unclaimed rewards and disable era for claiming
    function removeReward(uint256 era, address rewardAsset) public onlyAdmin {
      uint256 amount = mapEraAsset_Reward[era][rewardAsset];
      mapEraAsset_Reward[era][rewardAsset] = 0;
      mapAsset_Rewards[rewardAsset] = mapAsset_Rewards[rewardAsset].sub(
          amount
      );
      eraIsOpen[era] = false;
      require(
            ERC20(rewardAsset).transfer(treasury, amount),
            "Must transfer"
        );
    }

    // Quorum Action - Reuses adminApproveEraAsset() logic since unlikely to collide
    // Use in anger to sweep off assets (such as accidental airdropped tokens)
    function sweep(address asset, uint256 amount) public onlyAdmin {
      require(
            ERC20(asset).transfer(treasury, amount),
            "Must transfer"
        );
    }

    //============================== USER - LOCK/UNLOCK ================================//
    // Member locks some LP tokens
    function lock(address pool, uint256 amount) public nonReentrant {
        require(poolIsListed[pool] == true, "Must be listed");
        if (!isMember[msg.sender]) {
            // Add new member
            arrayMembers.push(msg.sender);
            isMember[msg.sender] = true;
        }
        if (!poolHasMembers[pool]) {
            // Records existence of member
            poolHasMembers[pool] = true;
        }
        if (!mapMemberPool_Added[msg.sender][pool]) {
            // Record all the pools member is in
            mapMember_poolCount[msg.sender] = mapMember_poolCount[msg.sender]
                .add(1);
            mapMember_arrayPools[msg.sender].push(pool);
            mapMemberPool_Added[msg.sender][pool] = true;
        }
        require(
            ERC20(pool).transferFrom(msg.sender, address(this), amount),
            "Must transfer"
        ); // Uni/Bal LP tokens return bool
        mapMemberPool_Balance[msg.sender][pool] = mapMemberPool_Balance[msg.sender][pool]
            .add(amount); // Record total pool balance for member
        registerClaim(msg.sender, pool, amount); // Register claim
        emit MemberLocks(msg.sender, pool, amount, currentEra);
    }

    // Member unlocks all from a pool
    function unlock(address pool) public nonReentrant {
        uint256 balance = mapMemberPool_Balance[msg.sender][pool];
        require(balance > 0, "Must have a balance to claim");
        mapMemberPool_Balance[msg.sender][pool] = 0; // Zero out balance
        require(ERC20(pool).transfer(msg.sender, balance), "Must transfer"); // Then transfer
        if (ERC20(pool).balanceOf(address(this)) == 0) {
            poolHasMembers[pool] = false; // If nobody is staking any more
        }
        emit MemberUnlocks(msg.sender, pool, balance, currentEra);
    }

    //============================== USER - CLAIM================================//
    // Member registers claim in a single pool
    function registerClaim(
        address member,
        address pool,
        uint256 amount
    ) internal {
        mapMemberEraPool_Claim[member][currentEra][pool] += amount;
        mapEraPool_Claims[currentEra][pool] = mapEraPool_Claims[currentEra][pool]
            .add(amount);
        emit MemberRegisters(member, pool, amount, currentEra);
    }

    // Member registers claim in all pools
    function registerAllClaims(address member) public {
        require(
            mapMemberEra_hasRegistered[msg.sender][currentEra] == false,
            "Must not have registered in this era already"
        );
        for (uint256 i = 0; i < mapMember_poolCount[member]; i++) {
            address pool = mapMember_arrayPools[member][i];
            // first deduct any previous claim
            mapEraPool_Claims[currentEra][pool] = mapEraPool_Claims[currentEra][pool]
                .sub(mapMemberEraPool_Claim[member][currentEra][pool]);
            uint256 amount = mapMemberPool_Balance[member][pool]; // then get latest balance
            mapMemberEraPool_Claim[member][currentEra][pool] = amount; // then update the claim
            mapEraPool_Claims[currentEra][pool] = mapEraPool_Claims[currentEra][pool]
                .add(amount); // then add to total
            emit MemberRegisters(member, pool, amount, currentEra);
        }
        mapMemberEra_hasRegistered[msg.sender][currentEra] = true;
    }

    // Member claims in a era
    function claim(uint256 era, address rewardAsset)
        public
        nonReentrant
    {
        require(
            mapMemberEraAsset_hasClaimed[msg.sender][era][rewardAsset] == false,
            "Reward asset must not have been claimed"
        );
        require(eraIsOpen[era], "Era must be opened");
        uint256 totalClaim = checkClaim(msg.sender, era);
        if (totalClaim > 0) {
            mapMemberEraAsset_hasClaimed[msg.sender][era][rewardAsset] = true; // Register claim
            mapEraAsset_Reward[era][rewardAsset] = mapEraAsset_Reward[era][rewardAsset]
                .sub(totalClaim); // Decrease rewards for that era
            mapAsset_Rewards[rewardAsset] = mapAsset_Rewards[rewardAsset].sub(
                totalClaim
            ); // Decrease rewards in total
            require(
                ERC20(rewardAsset).transfer(msg.sender, totalClaim),
                "Must transfer"
            ); // Then transfer
        }
        emit MemberClaims(msg.sender, era, totalClaim);
        if (mapMemberEra_hasRegistered[msg.sender][currentEra] == false) {
            registerAllClaims(msg.sender); // Register another claim
        }
    }

    // Member checks claims in all pools
    function checkClaim(address member, uint256 era)
        public
        view
        returns (uint256 totalClaim)
    {
        for (uint256 i = 0; i < mapMember_poolCount[member]; i++) {
            address pool = mapMember_arrayPools[member][i];
            totalClaim += checkClaimInPool(member, era, pool);
        }
        return totalClaim;
    }

    // Member checks claim in a single pool
    function checkClaimInPool(
        address member,
        uint256 era,
        address pool
    ) public view returns (uint256 claimShare) {
        uint256 poolShare = mapEraPool_Share[era][pool]; // Requires admin snapshotting for era first, else 0
        uint256 memberClaimInEra = mapMemberEraPool_Claim[member][era][pool]; // Requires member registering claim in the era
        uint256 totalClaimsInEra = mapEraPool_Claims[era][pool]; // Sum of all claims in a era
        if (totalClaimsInEra > 0) {
            // Requires non-zero balance of the pool tokens
            claimShare = getShare(
                memberClaimInEra,
                totalClaimsInEra,
                poolShare
            );
        } else {
            claimShare = 0;
        }
        return claimShare;
    }

    //==============================UTILS================================//
    // Get the share of a total
    function getShare(
        uint256 part,
        uint256 total,
        uint256 amount
    ) public pure returns (uint256 share) {
        return (amount.mul(part)).div(total);
    }

    function adminCount() public view returns (uint256) {
        return arrayAdmins.length;
    }

    function poolCount() public view returns (uint256) {
        return arrayPerlinPools.length;
    }

    function synthCount() public view returns (uint256) {
        return arraySynths.length;
    }

    function memberCount() public view returns (uint256) {
        return arrayMembers.length;
    }
}

Read Contract

PERL 0xc251adeb → address
adminCount 0x2b7832b3 → uint256
arrayAdmins 0x4445c1ea → address
arrayMembers 0x436f80be → address
arrayPerlinPools 0x32bc68be → address
arraySynths 0xeb765955 → address
checkClaim 0x0382ad26 → uint256
checkClaimInPool 0x3e66034f → uint256
currentEra 0x973628f6 → uint256
eraIsOpen 0xe07dbfbd → bool
getShare 0x69b30398 → uint256
isAdmin 0x24d7806c → bool
isMember 0xa230c524 → bool
mapAsset_Rewards 0x522cff25 → uint256
mapEraAsset_Reward 0x44d3d337 → uint256
mapEraPool_Balance 0x4dd85b5e → uint256
mapEraPool_Claims 0xf96e9ea1 → uint256
mapEraPool_Share 0x322e2604 → uint256
mapEra_Total 0x26b80529 → uint256
mapMemberEraAsset_hasClaimed 0xed06d4e2 → bool
mapMemberEraPool_Claim 0x44d7e455 → uint256
mapMemberEra_hasRegistered 0x31405c03 → bool
mapMemberPool_Added 0xe4ebdfa5 → bool
mapMemberPool_Balance 0x3d23e24a → uint256
mapMember_arrayPools 0xfa8f382a → address
mapMember_poolCount 0xce110e4b → uint256
mapPool_Asset 0xa19d1646 → address
mapSynth_EMP 0x5976c67c → address
memberCount 0x11aee380 → uint256
poolCount 0xf525cb68 → uint256
poolHasMembers 0x87e2662e → bool
poolIsListed 0x7f2277b4 → bool
poolWasListed 0x16d53471 → bool
poolWeight 0x8b5e608b → uint256
synthCount 0x78a45a24 → uint256
treasury 0x61d027b3 → address

Write Contract 15 functions

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

addAdmin 0x70480275
address newAdmin
claim 0xddd5e1b2
uint256 era
address rewardAsset
delistPool 0x306faf4a
address pool
listPool 0xbaff15ce
address pool
address asset
uint256 weight
listSynth 0x429d7e8f
address pool
address synth
address emp
uint256 weight
lock 0x282d3fdf
address pool
uint256 amount
registerAllClaims 0x845696b4
address member
removeReward 0x71586b1f
uint256 era
address rewardAsset
snapshot 0x26512160
address rewardAsset
snapshotInEra 0x4a5cab98
address rewardAsset
uint256 era
snapshotInEraWithOffset 0x3224e2f2
address rewardAsset
uint256 era
uint256 start
uint256 end
snapshotWithOffset 0xec7d7199
address rewardAsset
uint256 start
uint256 end
sweep 0x6ea056a9
address asset
uint256 amount
transferAdmin 0x75829def
address newAdmin
unlock 0x2f6c493c
address pool

Recent Transactions

This address has 1 on-chain transactions, but only 1.1% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →