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.

927 lines
36 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. HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
  16. HEZ "github.com/hermeznetwork/hermez-node/eth/contracts/tokenHEZ"
  17. "github.com/hermeznetwork/hermez-node/log"
  18. "github.com/hermeznetwork/tracerr"
  19. )
  20. // SlotState is the state of a slot
  21. type SlotState struct {
  22. Bidder ethCommon.Address
  23. ForgerCommitment bool
  24. Fulfilled bool
  25. BidAmount *big.Int
  26. ClosedMinBid *big.Int
  27. }
  28. // NewSlotState returns an empty SlotState
  29. func NewSlotState() *SlotState {
  30. return &SlotState{
  31. Bidder: ethCommon.Address{},
  32. Fulfilled: false,
  33. ForgerCommitment: false,
  34. BidAmount: big.NewInt(0),
  35. ClosedMinBid: big.NewInt(0),
  36. }
  37. }
  38. // Coordinator is the details of the Coordinator identified by the forger address
  39. type Coordinator struct {
  40. Forger ethCommon.Address
  41. URL string
  42. }
  43. // AuctionState represents the state of the Rollup in the Smart Contract
  44. type AuctionState struct {
  45. // Mapping to control slot state
  46. Slots map[int64]*SlotState
  47. // Mapping to control balances pending to claim
  48. PendingBalances map[ethCommon.Address]*big.Int
  49. // Mapping to register all the coordinators. The address used for the mapping is the forger address
  50. Coordinators map[ethCommon.Address]*Coordinator
  51. }
  52. // AuctionEventInitialize is the InitializeHermezAuctionProtocolEvent event of
  53. // the Smart Contract
  54. type AuctionEventInitialize struct {
  55. DonationAddress ethCommon.Address
  56. BootCoordinatorAddress ethCommon.Address
  57. BootCoordinatorURL string
  58. Outbidding uint16
  59. SlotDeadline uint8
  60. ClosedAuctionSlots uint16
  61. OpenAuctionSlots uint16
  62. AllocationRatio [3]uint16
  63. }
  64. // AuctionVariables returns the AuctionVariables from the initialize event
  65. func (ei *AuctionEventInitialize) AuctionVariables(InitialMinimalBidding *big.Int) *common.AuctionVariables {
  66. return &common.AuctionVariables{
  67. EthBlockNum: 0,
  68. DonationAddress: ei.DonationAddress,
  69. BootCoordinator: ei.BootCoordinatorAddress,
  70. BootCoordinatorURL: ei.BootCoordinatorURL,
  71. DefaultSlotSetBid: [6]*big.Int{
  72. InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
  73. InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
  74. },
  75. DefaultSlotSetBidSlotNum: 0,
  76. ClosedAuctionSlots: ei.ClosedAuctionSlots,
  77. OpenAuctionSlots: ei.OpenAuctionSlots,
  78. AllocationRatio: ei.AllocationRatio,
  79. Outbidding: ei.Outbidding,
  80. SlotDeadline: ei.SlotDeadline,
  81. }
  82. }
  83. // AuctionEventNewBid is an event of the Auction Smart Contract
  84. type AuctionEventNewBid struct {
  85. Slot int64
  86. BidAmount *big.Int
  87. Bidder ethCommon.Address
  88. }
  89. // AuctionEventNewSlotDeadline is an event of the Auction Smart Contract
  90. type AuctionEventNewSlotDeadline struct {
  91. NewSlotDeadline uint8
  92. }
  93. // AuctionEventNewClosedAuctionSlots is an event of the Auction Smart Contract
  94. type AuctionEventNewClosedAuctionSlots struct {
  95. NewClosedAuctionSlots uint16
  96. }
  97. // AuctionEventNewOutbidding is an event of the Auction Smart Contract
  98. type AuctionEventNewOutbidding struct {
  99. NewOutbidding uint16
  100. }
  101. // AuctionEventNewDonationAddress is an event of the Auction Smart Contract
  102. type AuctionEventNewDonationAddress struct {
  103. NewDonationAddress ethCommon.Address
  104. }
  105. // AuctionEventNewBootCoordinator is an event of the Auction Smart Contract
  106. type AuctionEventNewBootCoordinator struct {
  107. NewBootCoordinator ethCommon.Address
  108. NewBootCoordinatorURL string
  109. }
  110. // AuctionEventNewOpenAuctionSlots is an event of the Auction Smart Contract
  111. type AuctionEventNewOpenAuctionSlots struct {
  112. NewOpenAuctionSlots uint16
  113. }
  114. // AuctionEventNewAllocationRatio is an event of the Auction Smart Contract
  115. type AuctionEventNewAllocationRatio struct {
  116. NewAllocationRatio [3]uint16
  117. }
  118. // AuctionEventSetCoordinator is an event of the Auction Smart Contract
  119. type AuctionEventSetCoordinator struct {
  120. BidderAddress ethCommon.Address
  121. ForgerAddress ethCommon.Address
  122. CoordinatorURL string
  123. }
  124. // AuctionEventNewForgeAllocated is an event of the Auction Smart Contract
  125. type AuctionEventNewForgeAllocated struct {
  126. Bidder ethCommon.Address
  127. Forger ethCommon.Address
  128. SlotToForge int64
  129. BurnAmount *big.Int
  130. DonationAmount *big.Int
  131. GovernanceAmount *big.Int
  132. }
  133. // AuctionEventNewDefaultSlotSetBid is an event of the Auction Smart Contract
  134. type AuctionEventNewDefaultSlotSetBid struct {
  135. SlotSet int64
  136. NewInitialMinBid *big.Int
  137. }
  138. // AuctionEventNewForge is an event of the Auction Smart Contract
  139. type AuctionEventNewForge struct {
  140. Forger ethCommon.Address
  141. SlotToForge int64
  142. }
  143. // AuctionEventHEZClaimed is an event of the Auction Smart Contract
  144. type AuctionEventHEZClaimed struct {
  145. Owner ethCommon.Address
  146. Amount *big.Int
  147. }
  148. // AuctionEvents is the list of events in a block of the Auction Smart Contract
  149. type AuctionEvents struct {
  150. NewBid []AuctionEventNewBid
  151. NewSlotDeadline []AuctionEventNewSlotDeadline
  152. NewClosedAuctionSlots []AuctionEventNewClosedAuctionSlots
  153. NewOutbidding []AuctionEventNewOutbidding
  154. NewDonationAddress []AuctionEventNewDonationAddress
  155. NewBootCoordinator []AuctionEventNewBootCoordinator
  156. NewOpenAuctionSlots []AuctionEventNewOpenAuctionSlots
  157. NewAllocationRatio []AuctionEventNewAllocationRatio
  158. SetCoordinator []AuctionEventSetCoordinator
  159. NewForgeAllocated []AuctionEventNewForgeAllocated
  160. NewDefaultSlotSetBid []AuctionEventNewDefaultSlotSetBid
  161. NewForge []AuctionEventNewForge
  162. HEZClaimed []AuctionEventHEZClaimed
  163. }
  164. // NewAuctionEvents creates an empty AuctionEvents with the slices initialized.
  165. func NewAuctionEvents() AuctionEvents {
  166. return AuctionEvents{
  167. NewBid: make([]AuctionEventNewBid, 0),
  168. NewSlotDeadline: make([]AuctionEventNewSlotDeadline, 0),
  169. NewClosedAuctionSlots: make([]AuctionEventNewClosedAuctionSlots, 0),
  170. NewOutbidding: make([]AuctionEventNewOutbidding, 0),
  171. NewDonationAddress: make([]AuctionEventNewDonationAddress, 0),
  172. NewBootCoordinator: make([]AuctionEventNewBootCoordinator, 0),
  173. NewOpenAuctionSlots: make([]AuctionEventNewOpenAuctionSlots, 0),
  174. NewAllocationRatio: make([]AuctionEventNewAllocationRatio, 0),
  175. SetCoordinator: make([]AuctionEventSetCoordinator, 0),
  176. NewForgeAllocated: make([]AuctionEventNewForgeAllocated, 0),
  177. NewDefaultSlotSetBid: make([]AuctionEventNewDefaultSlotSetBid, 0),
  178. NewForge: make([]AuctionEventNewForge, 0),
  179. HEZClaimed: make([]AuctionEventHEZClaimed, 0),
  180. }
  181. }
  182. // AuctionInterface is the inteface to to Auction Smart Contract
  183. type AuctionInterface interface {
  184. //
  185. // Smart Contract Methods
  186. //
  187. // Getter/Setter, where Setter is onlyOwner
  188. AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error)
  189. AuctionGetSlotDeadline() (uint8, error)
  190. AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error)
  191. AuctionGetOpenAuctionSlots() (uint16, error)
  192. AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error)
  193. AuctionGetClosedAuctionSlots() (uint16, error)
  194. AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error)
  195. AuctionGetOutbidding() (uint16, error)
  196. AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error)
  197. AuctionGetAllocationRatio() ([3]uint16, error)
  198. AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error)
  199. AuctionGetDonationAddress() (*ethCommon.Address, error)
  200. AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (*types.Transaction, error)
  201. AuctionGetBootCoordinator() (*ethCommon.Address, error)
  202. AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error)
  203. // Coordinator Management
  204. AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (*types.Transaction, error)
  205. // Slot Info
  206. AuctionGetSlotNumber(blockNum int64) (int64, error)
  207. AuctionGetCurrentSlotNumber() (int64, error)
  208. AuctionGetMinBidBySlot(slot int64) (*big.Int, error)
  209. AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error)
  210. AuctionGetSlotSet(slot int64) (*big.Int, error)
  211. // Bidding
  212. AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error)
  213. AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
  214. maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error)
  215. // Forge
  216. AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error)
  217. AuctionForge(forger ethCommon.Address) (*types.Transaction, error)
  218. // Fees
  219. AuctionClaimHEZ() (*types.Transaction, error)
  220. AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error)
  221. //
  222. // Smart Contract Status
  223. //
  224. AuctionConstants() (*common.AuctionConstants, error)
  225. AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error)
  226. AuctionEventInit() (*AuctionEventInitialize, int64, error)
  227. }
  228. //
  229. // Implementation
  230. //
  231. // AuctionClient is the implementation of the interface to the Auction Smart Contract in ethereum.
  232. type AuctionClient struct {
  233. client *EthereumClient
  234. chainID *big.Int
  235. address ethCommon.Address
  236. tokenHEZCfg TokenConfig
  237. auction *HermezAuctionProtocol.HermezAuctionProtocol
  238. tokenHEZ *HEZ.HEZ
  239. contractAbi abi.ABI
  240. opts *bind.CallOpts
  241. }
  242. // NewAuctionClient creates a new AuctionClient. `tokenAddress` is the address of the HEZ tokens.
  243. func NewAuctionClient(client *EthereumClient, address ethCommon.Address, tokenHEZCfg TokenConfig) (*AuctionClient, error) {
  244. contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
  245. if err != nil {
  246. return nil, tracerr.Wrap(err)
  247. }
  248. auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(address, client.Client())
  249. if err != nil {
  250. return nil, tracerr.Wrap(err)
  251. }
  252. tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
  253. if err != nil {
  254. return nil, tracerr.Wrap(err)
  255. }
  256. chainID, err := client.EthChainID()
  257. if err != nil {
  258. return nil, tracerr.Wrap(err)
  259. }
  260. return &AuctionClient{
  261. client: client,
  262. chainID: chainID,
  263. address: address,
  264. tokenHEZCfg: tokenHEZCfg,
  265. auction: auction,
  266. tokenHEZ: tokenHEZ,
  267. contractAbi: contractAbi,
  268. opts: newCallOpts(),
  269. }, nil
  270. }
  271. // AuctionSetSlotDeadline is the interface to call the smart contract function
  272. func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
  273. var tx *types.Transaction
  274. var err error
  275. if tx, err = c.client.CallAuth(
  276. 0,
  277. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  278. return c.auction.SetSlotDeadline(auth, newDeadline)
  279. },
  280. ); err != nil {
  281. return nil, tracerr.Wrap(fmt.Errorf("Failed setting slotDeadline: %w", err))
  282. }
  283. return tx, nil
  284. }
  285. // AuctionGetSlotDeadline is the interface to call the smart contract function
  286. func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
  287. if err := c.client.Call(func(ec *ethclient.Client) error {
  288. slotDeadline, err = c.auction.GetSlotDeadline(c.opts)
  289. return tracerr.Wrap(err)
  290. }); err != nil {
  291. return 0, tracerr.Wrap(err)
  292. }
  293. return slotDeadline, nil
  294. }
  295. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  296. func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (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.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
  301. },
  302. ); err != nil {
  303. return nil, tracerr.Wrap(fmt.Errorf("Failed setting openAuctionSlots: %w", err))
  304. }
  305. return tx, nil
  306. }
  307. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  308. func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
  309. if err := c.client.Call(func(ec *ethclient.Client) error {
  310. openAuctionSlots, err = c.auction.GetOpenAuctionSlots(c.opts)
  311. return tracerr.Wrap(err)
  312. }); err != nil {
  313. return 0, tracerr.Wrap(err)
  314. }
  315. return openAuctionSlots, nil
  316. }
  317. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  318. func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  319. if tx, err = c.client.CallAuth(
  320. 0,
  321. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  322. return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
  323. },
  324. ); err != nil {
  325. return nil, tracerr.Wrap(fmt.Errorf("Failed setting closedAuctionSlots: %w", err))
  326. }
  327. return tx, nil
  328. }
  329. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  330. func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
  331. if err := c.client.Call(func(ec *ethclient.Client) error {
  332. closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(c.opts)
  333. return tracerr.Wrap(err)
  334. }); err != nil {
  335. return 0, tracerr.Wrap(err)
  336. }
  337. return closedAuctionSlots, nil
  338. }
  339. // AuctionSetOutbidding is the interface to call the smart contract function
  340. func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  341. if tx, err = c.client.CallAuth(
  342. 12500000, //nolint:gomnd
  343. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  344. return c.auction.SetOutbidding(auth, newOutbidding)
  345. },
  346. ); err != nil {
  347. return nil, tracerr.Wrap(fmt.Errorf("Failed setting setOutbidding: %w", err))
  348. }
  349. return tx, nil
  350. }
  351. // AuctionGetOutbidding is the interface to call the smart contract function
  352. func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
  353. if err := c.client.Call(func(ec *ethclient.Client) error {
  354. outbidding, err = c.auction.GetOutbidding(c.opts)
  355. return tracerr.Wrap(err)
  356. }); err != nil {
  357. return 0, tracerr.Wrap(err)
  358. }
  359. return outbidding, nil
  360. }
  361. // AuctionSetAllocationRatio is the interface to call the smart contract function
  362. func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  363. if tx, err = c.client.CallAuth(
  364. 0,
  365. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  366. return c.auction.SetAllocationRatio(auth, newAllocationRatio)
  367. },
  368. ); err != nil {
  369. return nil, tracerr.Wrap(fmt.Errorf("Failed setting allocationRatio: %w", err))
  370. }
  371. return tx, nil
  372. }
  373. // AuctionGetAllocationRatio is the interface to call the smart contract function
  374. func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
  375. if err := c.client.Call(func(ec *ethclient.Client) error {
  376. allocationRation, err = c.auction.GetAllocationRatio(c.opts)
  377. return tracerr.Wrap(err)
  378. }); err != nil {
  379. return [3]uint16{}, tracerr.Wrap(err)
  380. }
  381. return allocationRation, nil
  382. }
  383. // AuctionSetDonationAddress is the interface to call the smart contract function
  384. func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  385. if tx, err = c.client.CallAuth(
  386. 0,
  387. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  388. return c.auction.SetDonationAddress(auth, newDonationAddress)
  389. },
  390. ); err != nil {
  391. return nil, tracerr.Wrap(fmt.Errorf("Failed setting donationAddress: %w", err))
  392. }
  393. return tx, nil
  394. }
  395. // AuctionGetDonationAddress is the interface to call the smart contract function
  396. func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address, err error) {
  397. var _donationAddress ethCommon.Address
  398. if err := c.client.Call(func(ec *ethclient.Client) error {
  399. _donationAddress, err = c.auction.GetDonationAddress(c.opts)
  400. return tracerr.Wrap(err)
  401. }); err != nil {
  402. return nil, tracerr.Wrap(err)
  403. }
  404. return &_donationAddress, nil
  405. }
  406. // AuctionSetBootCoordinator is the interface to call the smart contract function
  407. func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
  408. if tx, err = c.client.CallAuth(
  409. 0,
  410. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  411. return c.auction.SetBootCoordinator(auth, newBootCoordinator, newBootCoordinatorURL)
  412. },
  413. ); err != nil {
  414. return nil, tracerr.Wrap(fmt.Errorf("Failed setting bootCoordinator: %w", err))
  415. }
  416. return tx, nil
  417. }
  418. // AuctionGetBootCoordinator is the interface to call the smart contract function
  419. func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address, err error) {
  420. var _bootCoordinator ethCommon.Address
  421. if err := c.client.Call(func(ec *ethclient.Client) error {
  422. _bootCoordinator, err = c.auction.GetBootCoordinator(c.opts)
  423. return tracerr.Wrap(err)
  424. }); err != nil {
  425. return nil, tracerr.Wrap(err)
  426. }
  427. return &_bootCoordinator, nil
  428. }
  429. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  430. func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  431. if tx, err = c.client.CallAuth(
  432. 0,
  433. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  434. slotSetToSend := big.NewInt(slotSet)
  435. return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
  436. },
  437. ); err != nil {
  438. return nil, tracerr.Wrap(fmt.Errorf("Failed changing slotSet Bid: %w", err))
  439. }
  440. return tx, nil
  441. }
  442. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  443. func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
  444. if err := c.client.Call(func(ec *ethclient.Client) error {
  445. claimableHEZ, err = c.auction.GetClaimableHEZ(c.opts, claimAddress)
  446. return tracerr.Wrap(err)
  447. }); err != nil {
  448. return nil, tracerr.Wrap(err)
  449. }
  450. return claimableHEZ, nil
  451. }
  452. // AuctionSetCoordinator is the interface to call the smart contract function
  453. func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (tx *types.Transaction, err error) {
  454. if tx, err = c.client.CallAuth(
  455. 0,
  456. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  457. return c.auction.SetCoordinator(auth, forger, coordinatorURL)
  458. },
  459. ); err != nil {
  460. return nil, tracerr.Wrap(fmt.Errorf("Failed set coordinator: %w", err))
  461. }
  462. return tx, nil
  463. }
  464. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  465. func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
  466. var _currentSlotNumber *big.Int
  467. if err := c.client.Call(func(ec *ethclient.Client) error {
  468. _currentSlotNumber, err = c.auction.GetCurrentSlotNumber(c.opts)
  469. return tracerr.Wrap(err)
  470. }); err != nil {
  471. return 0, tracerr.Wrap(err)
  472. }
  473. return _currentSlotNumber.Int64(), nil
  474. }
  475. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  476. func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
  477. if err := c.client.Call(func(ec *ethclient.Client) error {
  478. slotToSend := big.NewInt(slot)
  479. minBid, err = c.auction.GetMinBidBySlot(c.opts, slotToSend)
  480. return tracerr.Wrap(err)
  481. }); err != nil {
  482. return big.NewInt(0), tracerr.Wrap(err)
  483. }
  484. return minBid, nil
  485. }
  486. // AuctionGetSlotSet is the interface to call the smart contract function
  487. func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
  488. if err := c.client.Call(func(ec *ethclient.Client) error {
  489. slotToSend := big.NewInt(slot)
  490. slotSet, err = c.auction.GetSlotSet(c.opts, slotToSend)
  491. return tracerr.Wrap(err)
  492. }); err != nil {
  493. return big.NewInt(0), tracerr.Wrap(err)
  494. }
  495. return slotSet, nil
  496. }
  497. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  498. func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int, err error) {
  499. if err := c.client.Call(func(ec *ethclient.Client) error {
  500. minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(c.opts, slotSet)
  501. return tracerr.Wrap(err)
  502. }); err != nil {
  503. return big.NewInt(0), tracerr.Wrap(err)
  504. }
  505. return minBidSlotSet, nil
  506. }
  507. // AuctionGetSlotNumber is the interface to call the smart contract function
  508. func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
  509. var _slot *big.Int
  510. if err := c.client.Call(func(ec *ethclient.Client) error {
  511. _slot, err = c.auction.GetSlotNumber(c.opts, big.NewInt(blockNum))
  512. return tracerr.Wrap(err)
  513. }); err != nil {
  514. return 0, tracerr.Wrap(err)
  515. }
  516. return _slot.Int64(), nil
  517. }
  518. // AuctionBid is the interface to call the smart contract function
  519. func (c *AuctionClient) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error) {
  520. if tx, err = c.client.CallAuth(
  521. 0,
  522. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  523. owner := c.client.account.Address
  524. spender := c.address
  525. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  526. if err != nil {
  527. return nil, tracerr.Wrap(err)
  528. }
  529. tokenName := c.tokenHEZCfg.Name
  530. tokenAddr := c.tokenHEZCfg.Address
  531. digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
  532. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  533. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  534. _slot := big.NewInt(slot)
  535. return c.auction.ProcessBid(auth, amount, _slot, bidAmount, permit)
  536. },
  537. ); err != nil {
  538. return nil, tracerr.Wrap(fmt.Errorf("Failed bid: %w", err))
  539. }
  540. return tx, nil
  541. }
  542. // AuctionMultiBid is the interface to call the smart contract function
  543. func (c *AuctionClient) AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
  544. maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error) {
  545. if tx, err = c.client.CallAuth(
  546. 1000000, //nolint:gomnd
  547. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  548. owner := c.client.account.Address
  549. spender := c.address
  550. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  551. if err != nil {
  552. return nil, tracerr.Wrap(err)
  553. }
  554. tokenName := c.tokenHEZCfg.Name
  555. tokenAddr := c.tokenHEZCfg.Address
  556. digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
  557. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  558. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  559. _startingSlot := big.NewInt(startingSlot)
  560. _endingSlot := big.NewInt(endingSlot)
  561. return c.auction.ProcessMultiBid(auth, amount, _startingSlot, _endingSlot, slotSets, maxBid, minBid, permit)
  562. },
  563. ); err != nil {
  564. return nil, tracerr.Wrap(fmt.Errorf("Failed multibid: %w", err))
  565. }
  566. return tx, nil
  567. }
  568. // AuctionCanForge is the interface to call the smart contract function
  569. func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool, err error) {
  570. if err := c.client.Call(func(ec *ethclient.Client) error {
  571. canForge, err = c.auction.CanForge(c.opts, forger, big.NewInt(blockNum))
  572. return tracerr.Wrap(err)
  573. }); err != nil {
  574. return false, tracerr.Wrap(err)
  575. }
  576. return canForge, nil
  577. }
  578. // AuctionClaimHEZ is the interface to call the smart contract function
  579. func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  580. if tx, err = c.client.CallAuth(
  581. 0,
  582. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  583. return c.auction.ClaimHEZ(auth)
  584. },
  585. ); err != nil {
  586. return nil, tracerr.Wrap(fmt.Errorf("Failed claim HEZ: %w", err))
  587. }
  588. return tx, nil
  589. }
  590. // AuctionForge is the interface to call the smart contract function
  591. func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  592. if tx, err = c.client.CallAuth(
  593. 0,
  594. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  595. return c.auction.Forge(auth, forger)
  596. },
  597. ); err != nil {
  598. return nil, tracerr.Wrap(fmt.Errorf("Failed forge: %w", err))
  599. }
  600. return tx, nil
  601. }
  602. // AuctionConstants returns the Constants of the Auction Smart Contract
  603. func (c *AuctionClient) AuctionConstants() (auctionConstants *common.AuctionConstants, err error) {
  604. auctionConstants = new(common.AuctionConstants)
  605. if err := c.client.Call(func(ec *ethclient.Client) error {
  606. auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(c.opts)
  607. if err != nil {
  608. return tracerr.Wrap(err)
  609. }
  610. genesisBlock, err := c.auction.GenesisBlock(c.opts)
  611. if err != nil {
  612. return tracerr.Wrap(err)
  613. }
  614. auctionConstants.GenesisBlockNum = genesisBlock.Int64()
  615. auctionConstants.HermezRollup, err = c.auction.HermezRollup(c.opts)
  616. if err != nil {
  617. return tracerr.Wrap(err)
  618. }
  619. auctionConstants.InitialMinimalBidding, err = c.auction.INITIALMINIMALBIDDING(c.opts)
  620. if err != nil {
  621. return tracerr.Wrap(err)
  622. }
  623. auctionConstants.GovernanceAddress, err = c.auction.GovernanceAddress(c.opts)
  624. if err != nil {
  625. return tracerr.Wrap(err)
  626. }
  627. auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(c.opts)
  628. if err != nil {
  629. return tracerr.Wrap(err)
  630. }
  631. return nil
  632. }); err != nil {
  633. return nil, tracerr.Wrap(err)
  634. }
  635. return auctionConstants, nil
  636. }
  637. // AuctionVariables returns the variables of the Auction Smart Contract
  638. func (c *AuctionClient) AuctionVariables() (auctionVariables *common.AuctionVariables, err error) {
  639. auctionVariables = new(common.AuctionVariables)
  640. if err := c.client.Call(func(ec *ethclient.Client) error {
  641. auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
  642. if err != nil {
  643. return tracerr.Wrap(err)
  644. }
  645. bootCoordinator, err := c.AuctionGetBootCoordinator()
  646. if err != nil {
  647. return tracerr.Wrap(err)
  648. }
  649. auctionVariables.BootCoordinator = *bootCoordinator
  650. auctionVariables.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(c.opts)
  651. if err != nil {
  652. return tracerr.Wrap(err)
  653. }
  654. auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
  655. if err != nil {
  656. return tracerr.Wrap(err)
  657. }
  658. var defaultSlotSetBid [6]*big.Int
  659. for i := uint8(0); i < 6; i++ {
  660. bid, err := c.AuctionGetDefaultSlotSetBid(i)
  661. if err != nil {
  662. return tracerr.Wrap(err)
  663. }
  664. defaultSlotSetBid[i] = bid
  665. }
  666. auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
  667. donationAddress, err := c.AuctionGetDonationAddress()
  668. if err != nil {
  669. return tracerr.Wrap(err)
  670. }
  671. auctionVariables.DonationAddress = *donationAddress
  672. auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
  673. if err != nil {
  674. return tracerr.Wrap(err)
  675. }
  676. auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
  677. if err != nil {
  678. return tracerr.Wrap(err)
  679. }
  680. auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
  681. return tracerr.Wrap(err)
  682. }); err != nil {
  683. return nil, tracerr.Wrap(err)
  684. }
  685. return auctionVariables, nil
  686. }
  687. var (
  688. logAuctionNewBid = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
  689. logAuctionNewSlotDeadline = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
  690. logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
  691. logAuctionNewOutbidding = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
  692. logAuctionNewDonationAddress = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
  693. logAuctionNewBootCoordinator = crypto.Keccak256Hash([]byte("NewBootCoordinator(address,string)"))
  694. logAuctionNewOpenAuctionSlots = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
  695. logAuctionNewAllocationRatio = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
  696. logAuctionSetCoordinator = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
  697. logAuctionNewForgeAllocated = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
  698. logAuctionNewDefaultSlotSetBid = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
  699. logAuctionNewForge = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
  700. logAuctionHEZClaimed = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
  701. logAuctionInitialize = crypto.Keccak256Hash([]byte(
  702. "InitializeHermezAuctionProtocolEvent(address,address,string,uint16,uint8,uint16,uint16,uint16[3])"))
  703. )
  704. // AuctionEventInit returns the initialize event with its corresponding block number
  705. func (c *AuctionClient) AuctionEventInit() (*AuctionEventInitialize, int64, error) {
  706. query := ethereum.FilterQuery{
  707. Addresses: []ethCommon.Address{
  708. c.address,
  709. },
  710. Topics: [][]ethCommon.Hash{{logAuctionInitialize}},
  711. }
  712. logs, err := c.client.client.FilterLogs(context.Background(), query)
  713. if err != nil {
  714. return nil, 0, tracerr.Wrap(err)
  715. }
  716. if len(logs) != 1 {
  717. return nil, 0, tracerr.Wrap(fmt.Errorf("no event of type InitializeHermezAuctionProtocolEvent found"))
  718. }
  719. vLog := logs[0]
  720. if vLog.Topics[0] != logAuctionInitialize {
  721. return nil, 0, tracerr.Wrap(fmt.Errorf("event is not InitializeHermezAuctionProtocolEvent"))
  722. }
  723. var auctionInit AuctionEventInitialize
  724. if err := c.contractAbi.UnpackIntoInterface(&auctionInit,
  725. "InitializeHermezAuctionProtocolEvent", vLog.Data); err != nil {
  726. return nil, 0, tracerr.Wrap(err)
  727. }
  728. return &auctionInit, int64(vLog.BlockNumber), tracerr.Wrap(err)
  729. }
  730. // AuctionEventsByBlock returns the events in a block that happened in the
  731. // Auction Smart Contract and the blockHash where the eents happened. If there
  732. // are no events in that block, blockHash is nil.
  733. func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
  734. var auctionEvents AuctionEvents
  735. var blockHash *ethCommon.Hash
  736. query := ethereum.FilterQuery{
  737. FromBlock: big.NewInt(blockNum),
  738. ToBlock: big.NewInt(blockNum),
  739. Addresses: []ethCommon.Address{
  740. c.address,
  741. },
  742. Topics: [][]ethCommon.Hash{},
  743. }
  744. logs, err := c.client.client.FilterLogs(context.TODO(), query)
  745. if err != nil {
  746. return nil, nil, tracerr.Wrap(err)
  747. }
  748. if len(logs) > 0 {
  749. blockHash = &logs[0].BlockHash
  750. }
  751. for _, vLog := range logs {
  752. if vLog.BlockHash != *blockHash {
  753. log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
  754. return nil, nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
  755. }
  756. switch vLog.Topics[0] {
  757. case logAuctionNewBid:
  758. var auxNewBid struct {
  759. Slot *big.Int
  760. BidAmount *big.Int
  761. Address ethCommon.Address
  762. }
  763. var newBid AuctionEventNewBid
  764. if err := c.contractAbi.UnpackIntoInterface(&auxNewBid, "NewBid", vLog.Data); err != nil {
  765. return nil, nil, tracerr.Wrap(err)
  766. }
  767. newBid.BidAmount = auxNewBid.BidAmount
  768. newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  769. newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  770. auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
  771. case logAuctionNewSlotDeadline:
  772. var newSlotDeadline AuctionEventNewSlotDeadline
  773. if err := c.contractAbi.UnpackIntoInterface(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
  774. return nil, nil, tracerr.Wrap(err)
  775. }
  776. auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
  777. case logAuctionNewClosedAuctionSlots:
  778. var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
  779. if err := c.contractAbi.UnpackIntoInterface(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
  780. return nil, nil, tracerr.Wrap(err)
  781. }
  782. auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
  783. case logAuctionNewOutbidding:
  784. var newOutbidding AuctionEventNewOutbidding
  785. if err := c.contractAbi.UnpackIntoInterface(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
  786. return nil, nil, tracerr.Wrap(err)
  787. }
  788. auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
  789. case logAuctionNewDonationAddress:
  790. var newDonationAddress AuctionEventNewDonationAddress
  791. newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  792. auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
  793. case logAuctionNewBootCoordinator:
  794. var newBootCoordinator AuctionEventNewBootCoordinator
  795. if err := c.contractAbi.UnpackIntoInterface(&newBootCoordinator, "NewBootCoordinator", vLog.Data); err != nil {
  796. return nil, nil, tracerr.Wrap(err)
  797. }
  798. newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  799. auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
  800. case logAuctionNewOpenAuctionSlots:
  801. var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
  802. if err := c.contractAbi.UnpackIntoInterface(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
  803. return nil, nil, tracerr.Wrap(err)
  804. }
  805. auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
  806. case logAuctionNewAllocationRatio:
  807. var newAllocationRatio AuctionEventNewAllocationRatio
  808. if err := c.contractAbi.UnpackIntoInterface(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
  809. return nil, nil, tracerr.Wrap(err)
  810. }
  811. auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
  812. case logAuctionSetCoordinator:
  813. var setCoordinator AuctionEventSetCoordinator
  814. if err := c.contractAbi.UnpackIntoInterface(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
  815. return nil, nil, tracerr.Wrap(err)
  816. }
  817. setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  818. setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  819. auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
  820. case logAuctionNewForgeAllocated:
  821. var newForgeAllocated AuctionEventNewForgeAllocated
  822. if err := c.contractAbi.UnpackIntoInterface(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
  823. return nil, nil, tracerr.Wrap(err)
  824. }
  825. newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  826. newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  827. newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
  828. auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
  829. case logAuctionNewDefaultSlotSetBid:
  830. var auxNewDefaultSlotSetBid struct {
  831. SlotSet *big.Int
  832. NewInitialMinBid *big.Int
  833. }
  834. var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
  835. if err := c.contractAbi.UnpackIntoInterface(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
  836. return nil, nil, tracerr.Wrap(err)
  837. }
  838. newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
  839. newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
  840. auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
  841. case logAuctionNewForge:
  842. var newForge AuctionEventNewForge
  843. newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  844. newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
  845. auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
  846. case logAuctionHEZClaimed:
  847. var HEZClaimed AuctionEventHEZClaimed
  848. if err := c.contractAbi.UnpackIntoInterface(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
  849. return nil, nil, tracerr.Wrap(err)
  850. }
  851. HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  852. auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
  853. }
  854. }
  855. return &auctionEvents, blockHash, nil
  856. }