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.

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