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.

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