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.

463 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. }
  115. // NewWDelayerClient creates a new WDelayerClient
  116. func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) (*WDelayerClient, error) {
  117. contractAbi, err := abi.JSON(strings.NewReader(string(WithdrawalDelayer.WithdrawalDelayerABI)))
  118. if err != nil {
  119. return nil, tracerr.Wrap(err)
  120. }
  121. wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(address, client.Client())
  122. if err != nil {
  123. return nil, tracerr.Wrap(err)
  124. }
  125. return &WDelayerClient{
  126. client: client,
  127. address: address,
  128. wdelayer: wdelayer,
  129. contractAbi: contractAbi,
  130. }, nil
  131. }
  132. // WDelayerGetHermezGovernanceAddress is the interface to call the smart contract function
  133. func (c *WDelayerClient) WDelayerGetHermezGovernanceAddress() (hermezGovernanceAddress *ethCommon.Address, err error) {
  134. var _hermezGovernanceAddress ethCommon.Address
  135. if err := c.client.Call(func(ec *ethclient.Client) error {
  136. _hermezGovernanceAddress, err = c.wdelayer.GetHermezGovernanceAddress(nil)
  137. return tracerr.Wrap(err)
  138. }); err != nil {
  139. return nil, tracerr.Wrap(err)
  140. }
  141. return &_hermezGovernanceAddress, nil
  142. }
  143. // WDelayerTransferGovernance is the interface to call the smart contract function
  144. func (c *WDelayerClient) WDelayerTransferGovernance(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
  145. if tx, err = c.client.CallAuth(
  146. 0,
  147. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  148. return c.wdelayer.TransferGovernance(auth, newAddress)
  149. },
  150. ); err != nil {
  151. return nil, tracerr.Wrap(fmt.Errorf("Failed transfer hermezGovernanceAddress: %w", err))
  152. }
  153. return tx, nil
  154. }
  155. // WDelayerClaimGovernance is the interface to call the smart contract function
  156. func (c *WDelayerClient) WDelayerClaimGovernance() (tx *types.Transaction, err error) {
  157. if tx, err = c.client.CallAuth(
  158. 0,
  159. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  160. return c.wdelayer.ClaimGovernance(auth)
  161. },
  162. ); err != nil {
  163. return nil, tracerr.Wrap(fmt.Errorf("Failed claim hermezGovernanceAddress: %w", err))
  164. }
  165. return tx, nil
  166. }
  167. // WDelayerGetEmergencyCouncil is the interface to call the smart contract function
  168. func (c *WDelayerClient) WDelayerGetEmergencyCouncil() (emergencyCouncilAddress *ethCommon.Address, err error) {
  169. var _emergencyCouncilAddress ethCommon.Address
  170. if err := c.client.Call(func(ec *ethclient.Client) error {
  171. _emergencyCouncilAddress, err = c.wdelayer.GetEmergencyCouncil(nil)
  172. return tracerr.Wrap(err)
  173. }); err != nil {
  174. return nil, tracerr.Wrap(err)
  175. }
  176. return &_emergencyCouncilAddress, nil
  177. }
  178. // WDelayerTransferEmergencyCouncil is the interface to call the smart contract function
  179. func (c *WDelayerClient) WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
  180. if tx, err = c.client.CallAuth(
  181. 0,
  182. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  183. return c.wdelayer.TransferEmergencyCouncil(auth, newAddress)
  184. },
  185. ); err != nil {
  186. return nil, tracerr.Wrap(fmt.Errorf("Failed transfer EmergencyCouncil: %w", err))
  187. }
  188. return tx, nil
  189. }
  190. // WDelayerClaimEmergencyCouncil is the interface to call the smart contract function
  191. func (c *WDelayerClient) WDelayerClaimEmergencyCouncil() (tx *types.Transaction, err error) {
  192. if tx, err = c.client.CallAuth(
  193. 0,
  194. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  195. return c.wdelayer.ClaimEmergencyCouncil(auth)
  196. },
  197. ); err != nil {
  198. return nil, tracerr.Wrap(fmt.Errorf("Failed claim EmergencyCouncil: %w", err))
  199. }
  200. return tx, nil
  201. }
  202. // WDelayerIsEmergencyMode is the interface to call the smart contract function
  203. func (c *WDelayerClient) WDelayerIsEmergencyMode() (ermergencyMode bool, err error) {
  204. if err := c.client.Call(func(ec *ethclient.Client) error {
  205. ermergencyMode, err = c.wdelayer.IsEmergencyMode(nil)
  206. return tracerr.Wrap(err)
  207. }); err != nil {
  208. return false, tracerr.Wrap(err)
  209. }
  210. return ermergencyMode, nil
  211. }
  212. // WDelayerGetWithdrawalDelay is the interface to call the smart contract function
  213. func (c *WDelayerClient) WDelayerGetWithdrawalDelay() (withdrawalDelay *big.Int, err error) {
  214. if err := c.client.Call(func(ec *ethclient.Client) error {
  215. withdrawalDelay, err = c.wdelayer.GetWithdrawalDelay(nil)
  216. return tracerr.Wrap(err)
  217. }); err != nil {
  218. return nil, tracerr.Wrap(err)
  219. }
  220. return withdrawalDelay, nil
  221. }
  222. // WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
  223. func (c *WDelayerClient) WDelayerGetEmergencyModeStartingTime() (emergencyModeStartingTime *big.Int, err error) {
  224. if err := c.client.Call(func(ec *ethclient.Client) error {
  225. emergencyModeStartingTime, err = c.wdelayer.GetEmergencyModeStartingTime(nil)
  226. return tracerr.Wrap(err)
  227. }); err != nil {
  228. return nil, tracerr.Wrap(err)
  229. }
  230. return emergencyModeStartingTime, nil
  231. }
  232. // WDelayerEnableEmergencyMode is the interface to call the smart contract function
  233. func (c *WDelayerClient) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
  234. if tx, err = c.client.CallAuth(
  235. 0,
  236. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  237. return c.wdelayer.EnableEmergencyMode(auth)
  238. },
  239. ); err != nil {
  240. return nil, tracerr.Wrap(fmt.Errorf("Failed setting enable emergency mode: %w", err))
  241. }
  242. return tx, nil
  243. }
  244. // WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
  245. func (c *WDelayerClient) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
  246. if tx, err = c.client.CallAuth(
  247. 0,
  248. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  249. return c.wdelayer.ChangeWithdrawalDelay(auth, newWithdrawalDelay)
  250. },
  251. ); err != nil {
  252. return nil, tracerr.Wrap(fmt.Errorf("Failed setting withdrawal delay: %w", err))
  253. }
  254. return tx, nil
  255. }
  256. // WDelayerDepositInfo is the interface to call the smart contract function
  257. func (c *WDelayerClient) WDelayerDepositInfo(owner, token ethCommon.Address) (depositInfo DepositState, err error) {
  258. if err := c.client.Call(func(ec *ethclient.Client) error {
  259. amount, depositTimestamp, err := c.wdelayer.DepositInfo(nil, owner, token)
  260. depositInfo.Amount = amount
  261. depositInfo.DepositTimestamp = depositTimestamp
  262. return tracerr.Wrap(err)
  263. }); err != nil {
  264. return depositInfo, tracerr.Wrap(err)
  265. }
  266. return depositInfo, nil
  267. }
  268. // WDelayerDeposit is the interface to call the smart contract function
  269. func (c *WDelayerClient) WDelayerDeposit(owner, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
  270. if tx, err = c.client.CallAuth(
  271. 0,
  272. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  273. return c.wdelayer.Deposit(auth, owner, token, amount)
  274. },
  275. ); err != nil {
  276. return nil, tracerr.Wrap(fmt.Errorf("Failed deposit: %w", err))
  277. }
  278. return tx, nil
  279. }
  280. // WDelayerWithdrawal is the interface to call the smart contract function
  281. func (c *WDelayerClient) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
  282. if tx, err = c.client.CallAuth(
  283. 0,
  284. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  285. return c.wdelayer.Withdrawal(auth, owner, token)
  286. },
  287. ); err != nil {
  288. return nil, tracerr.Wrap(fmt.Errorf("Failed withdrawal: %w", err))
  289. }
  290. return tx, nil
  291. }
  292. // WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
  293. func (c *WDelayerClient) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
  294. if tx, err = c.client.CallAuth(
  295. 0,
  296. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  297. return c.wdelayer.EscapeHatchWithdrawal(auth, to, token, amount)
  298. },
  299. ); err != nil {
  300. return nil, tracerr.Wrap(fmt.Errorf("Failed escapeHatchWithdrawal: %w", err))
  301. }
  302. return tx, nil
  303. }
  304. // WDelayerConstants returns the Constants of the WDelayer Smart Contract
  305. func (c *WDelayerClient) WDelayerConstants() (constants *common.WDelayerConstants, err error) {
  306. constants = new(common.WDelayerConstants)
  307. if err := c.client.Call(func(ec *ethclient.Client) error {
  308. constants.MaxWithdrawalDelay, err = c.wdelayer.MAXWITHDRAWALDELAY(nil)
  309. if err != nil {
  310. return tracerr.Wrap(err)
  311. }
  312. constants.MaxEmergencyModeTime, err = c.wdelayer.MAXEMERGENCYMODETIME(nil)
  313. if err != nil {
  314. return tracerr.Wrap(err)
  315. }
  316. constants.HermezRollup, err = c.wdelayer.HermezRollupAddress(nil)
  317. if err != nil {
  318. return tracerr.Wrap(err)
  319. }
  320. return tracerr.Wrap(err)
  321. }); err != nil {
  322. return constants, tracerr.Wrap(err)
  323. }
  324. return constants, nil
  325. }
  326. var (
  327. logWDelayerDeposit = crypto.Keccak256Hash([]byte("Deposit(address,address,uint192,uint64)"))
  328. logWDelayerWithdraw = crypto.Keccak256Hash([]byte("Withdraw(address,address,uint192)"))
  329. logWDelayerEmergencyModeEnabled = crypto.Keccak256Hash([]byte("EmergencyModeEnabled()"))
  330. logWDelayerNewWithdrawalDelay = crypto.Keccak256Hash([]byte("NewWithdrawalDelay(uint64)"))
  331. logWDelayerEscapeHatchWithdrawal = crypto.Keccak256Hash([]byte("EscapeHatchWithdrawal(address,address,address,uint256)"))
  332. logWDelayerNewEmergencyCouncil = crypto.Keccak256Hash([]byte("NewEmergencyCouncil(address)"))
  333. logWDelayerNewHermezGovernanceAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceAddress(address)"))
  334. )
  335. // WDelayerEventsByBlock returns the events in a block that happened in the
  336. // WDelayer Smart Contract and the blockHash where the eents happened. If
  337. // there are no events in that block, blockHash is nil.
  338. func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) {
  339. var wdelayerEvents WDelayerEvents
  340. var blockHash *ethCommon.Hash
  341. query := ethereum.FilterQuery{
  342. FromBlock: big.NewInt(blockNum),
  343. ToBlock: big.NewInt(blockNum),
  344. Addresses: []ethCommon.Address{
  345. c.address,
  346. },
  347. BlockHash: nil,
  348. Topics: [][]ethCommon.Hash{},
  349. }
  350. logs, err := c.client.client.FilterLogs(context.Background(), query)
  351. if err != nil {
  352. return nil, nil, tracerr.Wrap(err)
  353. }
  354. if len(logs) > 0 {
  355. blockHash = &logs[0].BlockHash
  356. }
  357. for _, vLog := range logs {
  358. if vLog.BlockHash != *blockHash {
  359. log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
  360. return nil, nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
  361. }
  362. switch vLog.Topics[0] {
  363. case logWDelayerDeposit:
  364. var deposit WDelayerEventDeposit
  365. err := c.contractAbi.Unpack(&deposit, "Deposit", vLog.Data)
  366. if err != nil {
  367. return nil, nil, tracerr.Wrap(err)
  368. }
  369. deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  370. deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  371. deposit.TxHash = vLog.TxHash
  372. wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit)
  373. case logWDelayerWithdraw:
  374. var withdraw WDelayerEventWithdraw
  375. err := c.contractAbi.Unpack(&withdraw, "Withdraw", vLog.Data)
  376. if err != nil {
  377. return nil, nil, tracerr.Wrap(err)
  378. }
  379. withdraw.Token = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  380. withdraw.Owner = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  381. wdelayerEvents.Withdraw = append(wdelayerEvents.Withdraw, withdraw)
  382. case logWDelayerEmergencyModeEnabled:
  383. var emergencyModeEnabled WDelayerEventEmergencyModeEnabled
  384. wdelayerEvents.EmergencyModeEnabled = append(wdelayerEvents.EmergencyModeEnabled, emergencyModeEnabled)
  385. case logWDelayerNewWithdrawalDelay:
  386. var withdrawalDelay WDelayerEventNewWithdrawalDelay
  387. err := c.contractAbi.Unpack(&withdrawalDelay, "NewWithdrawalDelay", vLog.Data)
  388. if err != nil {
  389. return nil, nil, tracerr.Wrap(err)
  390. }
  391. wdelayerEvents.NewWithdrawalDelay = append(wdelayerEvents.NewWithdrawalDelay, withdrawalDelay)
  392. case logWDelayerEscapeHatchWithdrawal:
  393. var escapeHatchWithdrawal WDelayerEventEscapeHatchWithdrawal
  394. err := c.contractAbi.Unpack(&escapeHatchWithdrawal, "EscapeHatchWithdrawal", vLog.Data)
  395. if err != nil {
  396. return nil, nil, tracerr.Wrap(err)
  397. }
  398. escapeHatchWithdrawal.Who = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  399. escapeHatchWithdrawal.To = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  400. escapeHatchWithdrawal.Token = ethCommon.BytesToAddress(vLog.Topics[3].Bytes())
  401. wdelayerEvents.EscapeHatchWithdrawal = append(wdelayerEvents.EscapeHatchWithdrawal, escapeHatchWithdrawal)
  402. case logWDelayerNewEmergencyCouncil:
  403. var emergencyCouncil WDelayerEventNewEmergencyCouncil
  404. err := c.contractAbi.Unpack(&emergencyCouncil, "NewEmergencyCouncil", vLog.Data)
  405. if err != nil {
  406. return nil, nil, tracerr.Wrap(err)
  407. }
  408. wdelayerEvents.NewEmergencyCouncil = append(wdelayerEvents.NewEmergencyCouncil, emergencyCouncil)
  409. case logWDelayerNewHermezGovernanceAddress:
  410. var governanceAddress WDelayerEventNewHermezGovernanceAddress
  411. err := c.contractAbi.Unpack(&governanceAddress, "NewHermezGovernanceAddress", vLog.Data)
  412. if err != nil {
  413. return nil, nil, tracerr.Wrap(err)
  414. }
  415. wdelayerEvents.NewHermezGovernanceAddress = append(wdelayerEvents.NewHermezGovernanceAddress, governanceAddress)
  416. }
  417. }
  418. return &wdelayerEvents, blockHash, nil
  419. }