You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

456 lines
18 KiB

4 years ago
  1. package eth
  2. import (
  3. "context"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "github.com/ethereum/go-ethereum"
  8. "github.com/ethereum/go-ethereum/accounts/abi"
  9. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  10. ethCommon "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/core/types"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/ethereum/go-ethereum/ethclient"
  14. WithdrawalDelayer "github.com/hermeznetwork/hermez-node/eth/contracts/withdrawdelayer"
  15. )
  16. // WDelayerConstants are the constants of the Rollup Smart Contract
  17. type WDelayerConstants struct {
  18. // Max Withdrawal Delay
  19. MaxWithdrawalDelay uint64
  20. // Max Emergency mode time
  21. MaxEmergencyModeTime uint64
  22. // HermezRollup smartcontract address
  23. HermezRollup ethCommon.Address
  24. }
  25. // DepositState is the state of Deposit
  26. type DepositState struct {
  27. Amount *big.Int
  28. DepositTimestamp uint64
  29. }
  30. // WDelayerEventDeposit is an event of the WithdrawalDelayer Smart Contract
  31. type WDelayerEventDeposit struct {
  32. Owner ethCommon.Address
  33. Token ethCommon.Address
  34. Amount *big.Int
  35. DepositTimestamp uint64
  36. }
  37. // WDelayerEventWithdraw is an event of the WithdrawalDelayer Smart Contract
  38. type WDelayerEventWithdraw struct {
  39. Owner ethCommon.Address
  40. Token ethCommon.Address
  41. Amount *big.Int
  42. }
  43. // WDelayerEventEmergencyModeEnabled an event of the WithdrawalDelayer Smart Contract
  44. type WDelayerEventEmergencyModeEnabled struct {
  45. }
  46. // WDelayerEventNewWithdrawalDelay an event of the WithdrawalDelayer Smart Contract
  47. type WDelayerEventNewWithdrawalDelay struct {
  48. WithdrawalDelay uint64
  49. }
  50. // WDelayerEventEscapeHatchWithdrawal an event of the WithdrawalDelayer Smart Contract
  51. type WDelayerEventEscapeHatchWithdrawal struct {
  52. Who ethCommon.Address
  53. To ethCommon.Address
  54. Token ethCommon.Address
  55. Amount *big.Int
  56. }
  57. // WDelayerEventNewHermezKeeperAddress an event of the WithdrawalDelayer Smart Contract
  58. type WDelayerEventNewHermezKeeperAddress struct {
  59. NewHermezKeeperAddress ethCommon.Address
  60. }
  61. // WDelayerEventNewWhiteHackGroupAddress an event of the WithdrawalDelayer Smart Contract
  62. type WDelayerEventNewWhiteHackGroupAddress struct {
  63. NewWhiteHackGroupAddress ethCommon.Address
  64. }
  65. // WDelayerEventNewHermezGovernanceDAOAddress an event of the WithdrawalDelayer Smart Contract
  66. type WDelayerEventNewHermezGovernanceDAOAddress struct {
  67. NewHermezGovernanceDAOAddress ethCommon.Address
  68. }
  69. // WDelayerEvents is the lis of events in a block of the WithdrawalDelayer Smart Contract
  70. type WDelayerEvents struct {
  71. Deposit []WDelayerEventDeposit
  72. Withdraw []WDelayerEventWithdraw
  73. EmergencyModeEnabled []WDelayerEventEmergencyModeEnabled
  74. NewWithdrawalDelay []WDelayerEventNewWithdrawalDelay
  75. EscapeHatchWithdrawal []WDelayerEventEscapeHatchWithdrawal
  76. NewHermezKeeperAddress []WDelayerEventNewHermezKeeperAddress
  77. NewWhiteHackGroupAddress []WDelayerEventNewWhiteHackGroupAddress
  78. NewHermezGovernanceDAOAddress []WDelayerEventNewHermezGovernanceDAOAddress
  79. }
  80. // NewWDelayerEvents creates an empty WDelayerEvents with the slices initialized.
  81. func NewWDelayerEvents() WDelayerEvents {
  82. return WDelayerEvents{
  83. Deposit: make([]WDelayerEventDeposit, 0),
  84. Withdraw: make([]WDelayerEventWithdraw, 0),
  85. EmergencyModeEnabled: make([]WDelayerEventEmergencyModeEnabled, 0),
  86. NewWithdrawalDelay: make([]WDelayerEventNewWithdrawalDelay, 0),
  87. EscapeHatchWithdrawal: make([]WDelayerEventEscapeHatchWithdrawal, 0),
  88. NewHermezKeeperAddress: make([]WDelayerEventNewHermezKeeperAddress, 0),
  89. NewWhiteHackGroupAddress: make([]WDelayerEventNewWhiteHackGroupAddress, 0),
  90. NewHermezGovernanceDAOAddress: make([]WDelayerEventNewHermezGovernanceDAOAddress, 0),
  91. }
  92. }
  93. // WDelayerInterface is the inteface to WithdrawalDelayer Smart Contract
  94. type WDelayerInterface interface {
  95. //
  96. // Smart Contract Methods
  97. //
  98. WDelayerGetHermezGovernanceDAOAddress() (*ethCommon.Address, error)
  99. WDelayerSetHermezGovernanceDAOAddress(newAddress ethCommon.Address) (*types.Transaction, error)
  100. WDelayerGetHermezKeeperAddress() (*ethCommon.Address, error)
  101. WDelayerSetHermezKeeperAddress(newAddress ethCommon.Address) (*types.Transaction, error)
  102. WDelayerGetWhiteHackGroupAddress() (*ethCommon.Address, error)
  103. WDelayerSetWhiteHackGroupAddress(newAddress ethCommon.Address) (*types.Transaction, error)
  104. WDelayerIsEmergencyMode() (bool, error)
  105. WDelayerGetWithdrawalDelay() (*big.Int, error)
  106. WDelayerGetEmergencyModeStartingTime() (*big.Int, error)
  107. WDelayerEnableEmergencyMode() (*types.Transaction, error)
  108. WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (*types.Transaction, error)
  109. WDelayerDepositInfo(owner, token ethCommon.Address) (*big.Int, uint64)
  110. WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (*types.Transaction, error)
  111. WDelayerWithdrawal(owner, token ethCommon.Address) (*types.Transaction, error)
  112. WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (*types.Transaction, error)
  113. }
  114. //
  115. // Implementation
  116. //
  117. // WDelayerClient is the implementation of the interface to the WithdrawDelayer Smart Contract in ethereum.
  118. type WDelayerClient struct {
  119. client *EthereumClient
  120. address ethCommon.Address
  121. wdelayer *WithdrawalDelayer.WithdrawalDelayer
  122. contractAbi abi.ABI
  123. }
  124. // NewWDelayerClient creates a new WDelayerClient
  125. func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) (*WDelayerClient, error) {
  126. contractAbi, err := abi.JSON(strings.NewReader(string(WithdrawalDelayer.WithdrawalDelayerABI)))
  127. if err != nil {
  128. return nil, err
  129. }
  130. wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(address, client.Client())
  131. if err != nil {
  132. return nil, err
  133. }
  134. return &WDelayerClient{
  135. client: client,
  136. address: address,
  137. wdelayer: wdelayer,
  138. contractAbi: contractAbi,
  139. }, nil
  140. }
  141. // WDelayerGetHermezGovernanceDAOAddress is the interface to call the smart contract function
  142. func (c *WDelayerClient) WDelayerGetHermezGovernanceDAOAddress() (hermezGovernanceDAOAddress *ethCommon.Address, err error) {
  143. var _hermezGovernanceDAOAddress ethCommon.Address
  144. if err := c.client.Call(func(ec *ethclient.Client) error {
  145. _hermezGovernanceDAOAddress, err = c.wdelayer.GetHermezGovernanceDAOAddress(nil)
  146. return err
  147. }); err != nil {
  148. return nil, err
  149. }
  150. return &_hermezGovernanceDAOAddress, nil
  151. }
  152. // WDelayerSetHermezGovernanceDAOAddress is the interface to call the smart contract function
  153. func (c *WDelayerClient) WDelayerSetHermezGovernanceDAOAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
  154. if tx, err = c.client.CallAuth(
  155. 0,
  156. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  157. return c.wdelayer.SetHermezGovernanceDAOAddress(auth, newAddress)
  158. },
  159. ); err != nil {
  160. return nil, fmt.Errorf("Failed setting hermezGovernanceDAOAddress: %w", err)
  161. }
  162. return tx, nil
  163. }
  164. // WDelayerGetHermezKeeperAddress is the interface to call the smart contract function
  165. func (c *WDelayerClient) WDelayerGetHermezKeeperAddress() (hermezKeeperAddress *ethCommon.Address, err error) {
  166. var _hermezKeeperAddress ethCommon.Address
  167. if err := c.client.Call(func(ec *ethclient.Client) error {
  168. _hermezKeeperAddress, err = c.wdelayer.GetHermezKeeperAddress(nil)
  169. return err
  170. }); err != nil {
  171. return nil, err
  172. }
  173. return &_hermezKeeperAddress, nil
  174. }
  175. // WDelayerSetHermezKeeperAddress is the interface to call the smart contract function
  176. func (c *WDelayerClient) WDelayerSetHermezKeeperAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
  177. if tx, err = c.client.CallAuth(
  178. 0,
  179. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  180. return c.wdelayer.SetHermezKeeperAddress(auth, newAddress)
  181. },
  182. ); err != nil {
  183. return nil, fmt.Errorf("Failed setting hermezKeeperAddress: %w", err)
  184. }
  185. return tx, nil
  186. }
  187. // WDelayerGetWhiteHackGroupAddress is the interface to call the smart contract function
  188. func (c *WDelayerClient) WDelayerGetWhiteHackGroupAddress() (whiteHackGroupAddress *ethCommon.Address, err error) {
  189. var _whiteHackGroupAddress ethCommon.Address
  190. if err := c.client.Call(func(ec *ethclient.Client) error {
  191. _whiteHackGroupAddress, err = c.wdelayer.GetWhiteHackGroupAddress(nil)
  192. return err
  193. }); err != nil {
  194. return nil, err
  195. }
  196. return &_whiteHackGroupAddress, nil
  197. }
  198. // WDelayerSetWhiteHackGroupAddress is the interface to call the smart contract function
  199. func (c *WDelayerClient) WDelayerSetWhiteHackGroupAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
  200. if tx, err = c.client.CallAuth(
  201. 0,
  202. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  203. return c.wdelayer.SetWhiteHackGroupAddress(auth, newAddress)
  204. },
  205. ); err != nil {
  206. return nil, fmt.Errorf("Failed setting whiteHackGroupAddress: %w", err)
  207. }
  208. return tx, nil
  209. }
  210. // WDelayerIsEmergencyMode is the interface to call the smart contract function
  211. func (c *WDelayerClient) WDelayerIsEmergencyMode() (ermergencyMode bool, err error) {
  212. if err := c.client.Call(func(ec *ethclient.Client) error {
  213. ermergencyMode, err = c.wdelayer.IsEmergencyMode(nil)
  214. return err
  215. }); err != nil {
  216. return false, err
  217. }
  218. return ermergencyMode, nil
  219. }
  220. // WDelayerGetWithdrawalDelay is the interface to call the smart contract function
  221. func (c *WDelayerClient) WDelayerGetWithdrawalDelay() (withdrawalDelay *big.Int, err error) {
  222. if err := c.client.Call(func(ec *ethclient.Client) error {
  223. withdrawalDelay, err = c.wdelayer.GetWithdrawalDelay(nil)
  224. return err
  225. }); err != nil {
  226. return nil, err
  227. }
  228. return withdrawalDelay, nil
  229. }
  230. // WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
  231. func (c *WDelayerClient) WDelayerGetEmergencyModeStartingTime() (emergencyModeStartingTime *big.Int, err error) {
  232. if err := c.client.Call(func(ec *ethclient.Client) error {
  233. emergencyModeStartingTime, err = c.wdelayer.GetEmergencyModeStartingTime(nil)
  234. return err
  235. }); err != nil {
  236. return nil, err
  237. }
  238. return emergencyModeStartingTime, nil
  239. }
  240. // WDelayerEnableEmergencyMode is the interface to call the smart contract function
  241. func (c *WDelayerClient) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
  242. if tx, err = c.client.CallAuth(
  243. 0,
  244. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  245. return c.wdelayer.EnableEmergencyMode(auth)
  246. },
  247. ); err != nil {
  248. return nil, fmt.Errorf("Failed setting enable emergency mode: %w", err)
  249. }
  250. return tx, nil
  251. }
  252. // WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
  253. func (c *WDelayerClient) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
  254. if tx, err = c.client.CallAuth(
  255. 0,
  256. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  257. return c.wdelayer.ChangeWithdrawalDelay(auth, newWithdrawalDelay)
  258. },
  259. ); err != nil {
  260. return nil, fmt.Errorf("Failed setting withdrawal delay: %w", err)
  261. }
  262. return tx, nil
  263. }
  264. // WDelayerDepositInfo is the interface to call the smart contract function
  265. func (c *WDelayerClient) WDelayerDepositInfo(owner, token ethCommon.Address) (depositInfo DepositState, err error) {
  266. if err := c.client.Call(func(ec *ethclient.Client) error {
  267. amount, depositTimestamp, err := c.wdelayer.DepositInfo(nil, owner, token)
  268. depositInfo.Amount = amount
  269. depositInfo.DepositTimestamp = depositTimestamp
  270. return err
  271. }); err != nil {
  272. return depositInfo, err
  273. }
  274. return depositInfo, nil
  275. }
  276. // WDelayerDeposit is the interface to call the smart contract function
  277. func (c *WDelayerClient) WDelayerDeposit(owner, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
  278. if tx, err = c.client.CallAuth(
  279. 0,
  280. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  281. return c.wdelayer.Deposit(auth, owner, token, amount)
  282. },
  283. ); err != nil {
  284. return nil, fmt.Errorf("Failed deposit: %w", err)
  285. }
  286. return tx, nil
  287. }
  288. // WDelayerWithdrawal is the interface to call the smart contract function
  289. func (c *WDelayerClient) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
  290. if tx, err = c.client.CallAuth(
  291. 0,
  292. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  293. return c.wdelayer.Withdrawal(auth, owner, token)
  294. },
  295. ); err != nil {
  296. return nil, fmt.Errorf("Failed withdrawal: %w", err)
  297. }
  298. return tx, nil
  299. }
  300. // WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
  301. func (c *WDelayerClient) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
  302. if tx, err = c.client.CallAuth(
  303. 0,
  304. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  305. return c.wdelayer.EscapeHatchWithdrawal(auth, to, token, amount)
  306. },
  307. ); err != nil {
  308. return nil, fmt.Errorf("Failed escapeHatchWithdrawal: %w", err)
  309. }
  310. return tx, nil
  311. }
  312. var (
  313. logWDelayerDeposit = crypto.Keccak256Hash([]byte("Deposit(address,address,uint192,uint64)"))
  314. logWDelayerWithdraw = crypto.Keccak256Hash([]byte("Withdraw(address,address,uint192)"))
  315. logWDelayerEmergencyModeEnabled = crypto.Keccak256Hash([]byte("EmergencyModeEnabled()"))
  316. logWDelayerNewWithdrawalDelay = crypto.Keccak256Hash([]byte("NewWithdrawalDelay(uint64)"))
  317. logWDelayerEscapeHatchWithdrawal = crypto.Keccak256Hash([]byte("EscapeHatchWithdrawal(address,address,address,uint256)"))
  318. logWDelayerNewHermezKeeperAddress = crypto.Keccak256Hash([]byte("NewHermezKeeperAddress(address)"))
  319. logWDelayerNewWhiteHackGroupAddress = crypto.Keccak256Hash([]byte("NewWhiteHackGroupAddress(address)"))
  320. logWDelayerNewHermezGovernanceDAOAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceDAOAddress(address)"))
  321. )
  322. // WDelayerEventsByBlock returns the events in a block that happened in the
  323. // WDelayer Smart Contract and the blockHash where the eents happened. If
  324. // there are no events in that block, blockHash is nil.
  325. func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) {
  326. var wdelayerEvents WDelayerEvents
  327. var blockHash ethCommon.Hash
  328. query := ethereum.FilterQuery{
  329. FromBlock: big.NewInt(blockNum),
  330. ToBlock: big.NewInt(blockNum),
  331. Addresses: []ethCommon.Address{
  332. c.address,
  333. },
  334. BlockHash: nil,
  335. Topics: [][]ethCommon.Hash{},
  336. }
  337. logs, err := c.client.client.FilterLogs(context.Background(), query)
  338. if err != nil {
  339. return nil, nil, err
  340. }
  341. if len(logs) > 0 {
  342. blockHash = logs[0].BlockHash
  343. }
  344. for _, vLog := range logs {
  345. if vLog.BlockHash != blockHash {
  346. return nil, nil, ErrBlockHashMismatchEvent
  347. }
  348. switch vLog.Topics[0] {
  349. case logWDelayerDeposit:
  350. var deposit WDelayerEventDeposit
  351. err := c.contractAbi.Unpack(&deposit, "Deposit", vLog.Data)
  352. if err != nil {
  353. return nil, nil, err
  354. }
  355. deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  356. deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  357. wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit)
  358. case logWDelayerWithdraw:
  359. var withdraw WDelayerEventWithdraw
  360. err := c.contractAbi.Unpack(&withdraw, "Withdraw", vLog.Data)
  361. if err != nil {
  362. return nil, nil, err
  363. }
  364. withdraw.Token = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  365. withdraw.Owner = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  366. wdelayerEvents.Withdraw = append(wdelayerEvents.Withdraw, withdraw)
  367. case logWDelayerEmergencyModeEnabled:
  368. var emergencyModeEnabled WDelayerEventEmergencyModeEnabled
  369. wdelayerEvents.EmergencyModeEnabled = append(wdelayerEvents.EmergencyModeEnabled, emergencyModeEnabled)
  370. case logWDelayerNewWithdrawalDelay:
  371. var withdrawalDelay WDelayerEventNewWithdrawalDelay
  372. err := c.contractAbi.Unpack(&withdrawalDelay, "NewWithdrawalDelay", vLog.Data)
  373. if err != nil {
  374. return nil, nil, err
  375. }
  376. wdelayerEvents.NewWithdrawalDelay = append(wdelayerEvents.NewWithdrawalDelay, withdrawalDelay)
  377. case logWDelayerEscapeHatchWithdrawal:
  378. var escapeHatchWithdrawal WDelayerEventEscapeHatchWithdrawal
  379. err := c.contractAbi.Unpack(&escapeHatchWithdrawal, "EscapeHatchWithdrawal", vLog.Data)
  380. if err != nil {
  381. return nil, nil, err
  382. }
  383. escapeHatchWithdrawal.Who = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  384. escapeHatchWithdrawal.To = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  385. escapeHatchWithdrawal.Token = ethCommon.BytesToAddress(vLog.Topics[3].Bytes())
  386. wdelayerEvents.EscapeHatchWithdrawal = append(wdelayerEvents.EscapeHatchWithdrawal, escapeHatchWithdrawal)
  387. case logWDelayerNewHermezKeeperAddress:
  388. var keeperAddress WDelayerEventNewHermezKeeperAddress
  389. err := c.contractAbi.Unpack(&keeperAddress, "NewHermezKeeperAddress", vLog.Data)
  390. if err != nil {
  391. return nil, nil, err
  392. }
  393. wdelayerEvents.NewHermezKeeperAddress = append(wdelayerEvents.NewHermezKeeperAddress, keeperAddress)
  394. case logWDelayerNewWhiteHackGroupAddress:
  395. var whiteHackGroupAddress WDelayerEventNewWhiteHackGroupAddress
  396. err := c.contractAbi.Unpack(&whiteHackGroupAddress, "NewWhiteHackGroupAddress", vLog.Data)
  397. if err != nil {
  398. return nil, nil, err
  399. }
  400. wdelayerEvents.NewWhiteHackGroupAddress = append(wdelayerEvents.NewWhiteHackGroupAddress, whiteHackGroupAddress)
  401. case logWDelayerNewHermezGovernanceDAOAddress:
  402. var governanceDAOAddress WDelayerEventNewHermezGovernanceDAOAddress
  403. err := c.contractAbi.Unpack(&governanceDAOAddress, "NewHermezGovernanceDAOAddress", vLog.Data)
  404. if err != nil {
  405. return nil, nil, err
  406. }
  407. wdelayerEvents.NewHermezGovernanceDAOAddress = append(wdelayerEvents.NewHermezGovernanceDAOAddress, governanceDAOAddress)
  408. }
  409. }
  410. return &wdelayerEvents, &blockHash, nil
  411. }