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.

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