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.

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