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.

923 lines
35 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. address ethCommon.Address
  235. tokenHEZCfg TokenConfig
  236. auction *HermezAuctionProtocol.HermezAuctionProtocol
  237. tokenHEZ *HEZ.HEZ
  238. contractAbi abi.ABI
  239. opts *bind.CallOpts
  240. }
  241. // NewAuctionClient creates a new AuctionClient. `tokenAddress` is the address of the HEZ tokens.
  242. func NewAuctionClient(client *EthereumClient, address ethCommon.Address, tokenHEZCfg TokenConfig) (*AuctionClient, error) {
  243. contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
  244. if err != nil {
  245. return nil, tracerr.Wrap(err)
  246. }
  247. auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(address, client.Client())
  248. if err != nil {
  249. return nil, tracerr.Wrap(err)
  250. }
  251. tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
  252. if err != nil {
  253. return nil, tracerr.Wrap(err)
  254. }
  255. return &AuctionClient{
  256. client: client,
  257. address: address,
  258. tokenHEZCfg: tokenHEZCfg,
  259. auction: auction,
  260. tokenHEZ: tokenHEZ,
  261. contractAbi: contractAbi,
  262. opts: newCallOpts(),
  263. }, nil
  264. }
  265. // AuctionSetSlotDeadline is the interface to call the smart contract function
  266. func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
  267. var tx *types.Transaction
  268. var err error
  269. if tx, err = c.client.CallAuth(
  270. 0,
  271. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  272. return c.auction.SetSlotDeadline(auth, newDeadline)
  273. },
  274. ); err != nil {
  275. return nil, tracerr.Wrap(fmt.Errorf("Failed setting slotDeadline: %w", err))
  276. }
  277. return tx, nil
  278. }
  279. // AuctionGetSlotDeadline is the interface to call the smart contract function
  280. func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
  281. if err := c.client.Call(func(ec *ethclient.Client) error {
  282. slotDeadline, err = c.auction.GetSlotDeadline(c.opts)
  283. return tracerr.Wrap(err)
  284. }); err != nil {
  285. return 0, tracerr.Wrap(err)
  286. }
  287. return slotDeadline, nil
  288. }
  289. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  290. func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  291. if tx, err = c.client.CallAuth(
  292. 0,
  293. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  294. return c.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
  295. },
  296. ); err != nil {
  297. return nil, tracerr.Wrap(fmt.Errorf("Failed setting openAuctionSlots: %w", err))
  298. }
  299. return tx, nil
  300. }
  301. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  302. func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
  303. if err := c.client.Call(func(ec *ethclient.Client) error {
  304. openAuctionSlots, err = c.auction.GetOpenAuctionSlots(c.opts)
  305. return tracerr.Wrap(err)
  306. }); err != nil {
  307. return 0, tracerr.Wrap(err)
  308. }
  309. return openAuctionSlots, nil
  310. }
  311. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  312. func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  313. if tx, err = c.client.CallAuth(
  314. 0,
  315. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  316. return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
  317. },
  318. ); err != nil {
  319. return nil, tracerr.Wrap(fmt.Errorf("Failed setting closedAuctionSlots: %w", err))
  320. }
  321. return tx, nil
  322. }
  323. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  324. func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
  325. if err := c.client.Call(func(ec *ethclient.Client) error {
  326. closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(c.opts)
  327. return tracerr.Wrap(err)
  328. }); err != nil {
  329. return 0, tracerr.Wrap(err)
  330. }
  331. return closedAuctionSlots, nil
  332. }
  333. // AuctionSetOutbidding is the interface to call the smart contract function
  334. func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  335. if tx, err = c.client.CallAuth(
  336. 12500000, //nolint:gomnd
  337. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  338. return c.auction.SetOutbidding(auth, newOutbidding)
  339. },
  340. ); err != nil {
  341. return nil, tracerr.Wrap(fmt.Errorf("Failed setting setOutbidding: %w", err))
  342. }
  343. return tx, nil
  344. }
  345. // AuctionGetOutbidding is the interface to call the smart contract function
  346. func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
  347. if err := c.client.Call(func(ec *ethclient.Client) error {
  348. outbidding, err = c.auction.GetOutbidding(c.opts)
  349. return tracerr.Wrap(err)
  350. }); err != nil {
  351. return 0, tracerr.Wrap(err)
  352. }
  353. return outbidding, nil
  354. }
  355. // AuctionSetAllocationRatio is the interface to call the smart contract function
  356. func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  357. if tx, err = c.client.CallAuth(
  358. 0,
  359. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  360. return c.auction.SetAllocationRatio(auth, newAllocationRatio)
  361. },
  362. ); err != nil {
  363. return nil, tracerr.Wrap(fmt.Errorf("Failed setting allocationRatio: %w", err))
  364. }
  365. return tx, nil
  366. }
  367. // AuctionGetAllocationRatio is the interface to call the smart contract function
  368. func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
  369. if err := c.client.Call(func(ec *ethclient.Client) error {
  370. allocationRation, err = c.auction.GetAllocationRatio(c.opts)
  371. return tracerr.Wrap(err)
  372. }); err != nil {
  373. return [3]uint16{}, tracerr.Wrap(err)
  374. }
  375. return allocationRation, nil
  376. }
  377. // AuctionSetDonationAddress is the interface to call the smart contract function
  378. func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  379. if tx, err = c.client.CallAuth(
  380. 0,
  381. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  382. return c.auction.SetDonationAddress(auth, newDonationAddress)
  383. },
  384. ); err != nil {
  385. return nil, tracerr.Wrap(fmt.Errorf("Failed setting donationAddress: %w", err))
  386. }
  387. return tx, nil
  388. }
  389. // AuctionGetDonationAddress is the interface to call the smart contract function
  390. func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address, err error) {
  391. var _donationAddress ethCommon.Address
  392. if err := c.client.Call(func(ec *ethclient.Client) error {
  393. _donationAddress, err = c.auction.GetDonationAddress(c.opts)
  394. return tracerr.Wrap(err)
  395. }); err != nil {
  396. return nil, tracerr.Wrap(err)
  397. }
  398. return &_donationAddress, nil
  399. }
  400. // AuctionSetBootCoordinator is the interface to call the smart contract function
  401. func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
  402. if tx, err = c.client.CallAuth(
  403. 0,
  404. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  405. return c.auction.SetBootCoordinator(auth, newBootCoordinator, newBootCoordinatorURL)
  406. },
  407. ); err != nil {
  408. return nil, tracerr.Wrap(fmt.Errorf("Failed setting bootCoordinator: %w", err))
  409. }
  410. return tx, nil
  411. }
  412. // AuctionGetBootCoordinator is the interface to call the smart contract function
  413. func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address, err error) {
  414. var _bootCoordinator ethCommon.Address
  415. if err := c.client.Call(func(ec *ethclient.Client) error {
  416. _bootCoordinator, err = c.auction.GetBootCoordinator(c.opts)
  417. return tracerr.Wrap(err)
  418. }); err != nil {
  419. return nil, tracerr.Wrap(err)
  420. }
  421. return &_bootCoordinator, nil
  422. }
  423. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  424. func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  425. if tx, err = c.client.CallAuth(
  426. 0,
  427. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  428. slotSetToSend := big.NewInt(slotSet)
  429. return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
  430. },
  431. ); err != nil {
  432. return nil, tracerr.Wrap(fmt.Errorf("Failed changing slotSet Bid: %w", err))
  433. }
  434. return tx, nil
  435. }
  436. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  437. func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
  438. if err := c.client.Call(func(ec *ethclient.Client) error {
  439. claimableHEZ, err = c.auction.GetClaimableHEZ(c.opts, claimAddress)
  440. return tracerr.Wrap(err)
  441. }); err != nil {
  442. return nil, tracerr.Wrap(err)
  443. }
  444. return claimableHEZ, nil
  445. }
  446. // AuctionSetCoordinator is the interface to call the smart contract function
  447. func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (tx *types.Transaction, err error) {
  448. if tx, err = c.client.CallAuth(
  449. 0,
  450. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  451. return c.auction.SetCoordinator(auth, forger, coordinatorURL)
  452. },
  453. ); err != nil {
  454. return nil, tracerr.Wrap(fmt.Errorf("Failed set coordinator: %w", err))
  455. }
  456. return tx, nil
  457. }
  458. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  459. func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
  460. var _currentSlotNumber *big.Int
  461. if err := c.client.Call(func(ec *ethclient.Client) error {
  462. _currentSlotNumber, err = c.auction.GetCurrentSlotNumber(c.opts)
  463. return tracerr.Wrap(err)
  464. }); err != nil {
  465. return 0, tracerr.Wrap(err)
  466. }
  467. return _currentSlotNumber.Int64(), nil
  468. }
  469. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  470. func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
  471. if err := c.client.Call(func(ec *ethclient.Client) error {
  472. slotToSend := big.NewInt(slot)
  473. minBid, err = c.auction.GetMinBidBySlot(c.opts, slotToSend)
  474. return tracerr.Wrap(err)
  475. }); err != nil {
  476. return big.NewInt(0), tracerr.Wrap(err)
  477. }
  478. return minBid, nil
  479. }
  480. // AuctionGetSlotSet is the interface to call the smart contract function
  481. func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
  482. if err := c.client.Call(func(ec *ethclient.Client) error {
  483. slotToSend := big.NewInt(slot)
  484. slotSet, err = c.auction.GetSlotSet(c.opts, slotToSend)
  485. return tracerr.Wrap(err)
  486. }); err != nil {
  487. return big.NewInt(0), tracerr.Wrap(err)
  488. }
  489. return slotSet, nil
  490. }
  491. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  492. func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int, err error) {
  493. if err := c.client.Call(func(ec *ethclient.Client) error {
  494. minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(c.opts, slotSet)
  495. return tracerr.Wrap(err)
  496. }); err != nil {
  497. return big.NewInt(0), tracerr.Wrap(err)
  498. }
  499. return minBidSlotSet, nil
  500. }
  501. // AuctionGetSlotNumber is the interface to call the smart contract function
  502. func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
  503. var _slot *big.Int
  504. if err := c.client.Call(func(ec *ethclient.Client) error {
  505. _slot, err = c.auction.GetSlotNumber(c.opts, big.NewInt(blockNum))
  506. return tracerr.Wrap(err)
  507. }); err != nil {
  508. return 0, tracerr.Wrap(err)
  509. }
  510. return _slot.Int64(), nil
  511. }
  512. // AuctionBid is the interface to call the smart contract function
  513. func (c *AuctionClient) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error) {
  514. if tx, err = c.client.CallAuth(
  515. 0,
  516. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  517. owner := c.client.account.Address
  518. spender := c.address
  519. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  520. if err != nil {
  521. return nil, tracerr.Wrap(err)
  522. }
  523. tokenName := c.tokenHEZCfg.Name
  524. tokenAddr := c.tokenHEZCfg.Address
  525. chainid, _ := c.client.Client().ChainID(context.Background())
  526. digest, _ := createPermitDigest(tokenAddr, owner, spender, chainid, amount, nonce, deadline, tokenName)
  527. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  528. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  529. _slot := big.NewInt(slot)
  530. return c.auction.ProcessBid(auth, amount, _slot, bidAmount, permit)
  531. },
  532. ); err != nil {
  533. return nil, tracerr.Wrap(fmt.Errorf("Failed bid: %w", err))
  534. }
  535. return tx, nil
  536. }
  537. // AuctionMultiBid is the interface to call the smart contract function
  538. func (c *AuctionClient) AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
  539. maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error) {
  540. if tx, err = c.client.CallAuth(
  541. 1000000, //nolint:gomnd
  542. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  543. owner := c.client.account.Address
  544. spender := c.address
  545. nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
  546. if err != nil {
  547. return nil, tracerr.Wrap(err)
  548. }
  549. tokenName := c.tokenHEZCfg.Name
  550. tokenAddr := c.tokenHEZCfg.Address
  551. chainid, _ := c.client.Client().ChainID(context.Background())
  552. digest, _ := createPermitDigest(tokenAddr, owner, spender, chainid, amount, nonce, deadline, tokenName)
  553. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  554. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  555. _startingSlot := big.NewInt(startingSlot)
  556. _endingSlot := big.NewInt(endingSlot)
  557. return c.auction.ProcessMultiBid(auth, amount, _startingSlot, _endingSlot, slotSets, maxBid, minBid, permit)
  558. },
  559. ); err != nil {
  560. return nil, tracerr.Wrap(fmt.Errorf("Failed multibid: %w", err))
  561. }
  562. return tx, nil
  563. }
  564. // AuctionCanForge is the interface to call the smart contract function
  565. func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool, err error) {
  566. if err := c.client.Call(func(ec *ethclient.Client) error {
  567. canForge, err = c.auction.CanForge(c.opts, forger, big.NewInt(blockNum))
  568. return tracerr.Wrap(err)
  569. }); err != nil {
  570. return false, tracerr.Wrap(err)
  571. }
  572. return canForge, nil
  573. }
  574. // AuctionClaimHEZ is the interface to call the smart contract function
  575. func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  576. if tx, err = c.client.CallAuth(
  577. 0,
  578. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  579. return c.auction.ClaimHEZ(auth)
  580. },
  581. ); err != nil {
  582. return nil, tracerr.Wrap(fmt.Errorf("Failed claim HEZ: %w", err))
  583. }
  584. return tx, nil
  585. }
  586. // AuctionForge is the interface to call the smart contract function
  587. func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  588. if tx, err = c.client.CallAuth(
  589. 0,
  590. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  591. return c.auction.Forge(auth, forger)
  592. },
  593. ); err != nil {
  594. return nil, tracerr.Wrap(fmt.Errorf("Failed forge: %w", err))
  595. }
  596. return tx, nil
  597. }
  598. // AuctionConstants returns the Constants of the Auction Smart Contract
  599. func (c *AuctionClient) AuctionConstants() (auctionConstants *common.AuctionConstants, err error) {
  600. auctionConstants = new(common.AuctionConstants)
  601. if err := c.client.Call(func(ec *ethclient.Client) error {
  602. auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(c.opts)
  603. if err != nil {
  604. return tracerr.Wrap(err)
  605. }
  606. genesisBlock, err := c.auction.GenesisBlock(c.opts)
  607. if err != nil {
  608. return tracerr.Wrap(err)
  609. }
  610. auctionConstants.GenesisBlockNum = genesisBlock.Int64()
  611. auctionConstants.HermezRollup, err = c.auction.HermezRollup(c.opts)
  612. if err != nil {
  613. return tracerr.Wrap(err)
  614. }
  615. auctionConstants.InitialMinimalBidding, err = c.auction.INITIALMINIMALBIDDING(c.opts)
  616. if err != nil {
  617. return tracerr.Wrap(err)
  618. }
  619. auctionConstants.GovernanceAddress, err = c.auction.GovernanceAddress(c.opts)
  620. if err != nil {
  621. return tracerr.Wrap(err)
  622. }
  623. auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(c.opts)
  624. if err != nil {
  625. return tracerr.Wrap(err)
  626. }
  627. return nil
  628. }); err != nil {
  629. return nil, tracerr.Wrap(err)
  630. }
  631. return auctionConstants, nil
  632. }
  633. // AuctionVariables returns the variables of the Auction Smart Contract
  634. func (c *AuctionClient) AuctionVariables() (auctionVariables *common.AuctionVariables, err error) {
  635. auctionVariables = new(common.AuctionVariables)
  636. if err := c.client.Call(func(ec *ethclient.Client) error {
  637. auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
  638. if err != nil {
  639. return tracerr.Wrap(err)
  640. }
  641. bootCoordinator, err := c.AuctionGetBootCoordinator()
  642. if err != nil {
  643. return tracerr.Wrap(err)
  644. }
  645. auctionVariables.BootCoordinator = *bootCoordinator
  646. auctionVariables.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(c.opts)
  647. if err != nil {
  648. return tracerr.Wrap(err)
  649. }
  650. auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
  651. if err != nil {
  652. return tracerr.Wrap(err)
  653. }
  654. var defaultSlotSetBid [6]*big.Int
  655. for i := uint8(0); i < 6; i++ {
  656. bid, err := c.AuctionGetDefaultSlotSetBid(i)
  657. if err != nil {
  658. return tracerr.Wrap(err)
  659. }
  660. defaultSlotSetBid[i] = bid
  661. }
  662. auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
  663. donationAddress, err := c.AuctionGetDonationAddress()
  664. if err != nil {
  665. return tracerr.Wrap(err)
  666. }
  667. auctionVariables.DonationAddress = *donationAddress
  668. auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
  669. if err != nil {
  670. return tracerr.Wrap(err)
  671. }
  672. auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
  673. if err != nil {
  674. return tracerr.Wrap(err)
  675. }
  676. auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
  677. return tracerr.Wrap(err)
  678. }); err != nil {
  679. return nil, tracerr.Wrap(err)
  680. }
  681. return auctionVariables, nil
  682. }
  683. var (
  684. logAuctionNewBid = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
  685. logAuctionNewSlotDeadline = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
  686. logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
  687. logAuctionNewOutbidding = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
  688. logAuctionNewDonationAddress = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
  689. logAuctionNewBootCoordinator = crypto.Keccak256Hash([]byte("NewBootCoordinator(address,string)"))
  690. logAuctionNewOpenAuctionSlots = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
  691. logAuctionNewAllocationRatio = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
  692. logAuctionSetCoordinator = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
  693. logAuctionNewForgeAllocated = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
  694. logAuctionNewDefaultSlotSetBid = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
  695. logAuctionNewForge = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
  696. logAuctionHEZClaimed = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
  697. logAuctionInitialize = crypto.Keccak256Hash([]byte(
  698. "InitializeHermezAuctionProtocolEvent(address,address,string,uint16,uint8,uint16,uint16,uint16[3])"))
  699. )
  700. // AuctionEventInit returns the initialize event with its corresponding block number
  701. func (c *AuctionClient) AuctionEventInit() (*AuctionEventInitialize, int64, error) {
  702. query := ethereum.FilterQuery{
  703. Addresses: []ethCommon.Address{
  704. c.address,
  705. },
  706. Topics: [][]ethCommon.Hash{{logAuctionInitialize}},
  707. }
  708. logs, err := c.client.client.FilterLogs(context.Background(), query)
  709. if err != nil {
  710. return nil, 0, tracerr.Wrap(err)
  711. }
  712. if len(logs) != 1 {
  713. return nil, 0, fmt.Errorf("no event of type InitializeHermezAuctionProtocolEvent found")
  714. }
  715. vLog := logs[0]
  716. if vLog.Topics[0] != logAuctionInitialize {
  717. return nil, 0, fmt.Errorf("event is not InitializeHermezAuctionProtocolEvent")
  718. }
  719. var auctionInit AuctionEventInitialize
  720. if err := c.contractAbi.UnpackIntoInterface(&auctionInit,
  721. "InitializeHermezAuctionProtocolEvent", vLog.Data); err != nil {
  722. return nil, 0, tracerr.Wrap(err)
  723. }
  724. return &auctionInit, int64(vLog.BlockNumber), err
  725. }
  726. // AuctionEventsByBlock returns the events in a block that happened in the
  727. // Auction Smart Contract and the blockHash where the eents happened. If there
  728. // are no events in that block, blockHash is nil.
  729. func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
  730. var auctionEvents AuctionEvents
  731. var blockHash *ethCommon.Hash
  732. query := ethereum.FilterQuery{
  733. FromBlock: big.NewInt(blockNum),
  734. ToBlock: big.NewInt(blockNum),
  735. Addresses: []ethCommon.Address{
  736. c.address,
  737. },
  738. Topics: [][]ethCommon.Hash{},
  739. }
  740. logs, err := c.client.client.FilterLogs(context.TODO(), query)
  741. if err != nil {
  742. return nil, nil, tracerr.Wrap(err)
  743. }
  744. if len(logs) > 0 {
  745. blockHash = &logs[0].BlockHash
  746. }
  747. for _, vLog := range logs {
  748. if vLog.BlockHash != *blockHash {
  749. log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
  750. return nil, nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
  751. }
  752. switch vLog.Topics[0] {
  753. case logAuctionNewBid:
  754. var auxNewBid struct {
  755. Slot *big.Int
  756. BidAmount *big.Int
  757. Address ethCommon.Address
  758. }
  759. var newBid AuctionEventNewBid
  760. if err := c.contractAbi.UnpackIntoInterface(&auxNewBid, "NewBid", vLog.Data); err != nil {
  761. return nil, nil, tracerr.Wrap(err)
  762. }
  763. newBid.BidAmount = auxNewBid.BidAmount
  764. newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  765. newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  766. auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
  767. case logAuctionNewSlotDeadline:
  768. var newSlotDeadline AuctionEventNewSlotDeadline
  769. if err := c.contractAbi.UnpackIntoInterface(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
  770. return nil, nil, tracerr.Wrap(err)
  771. }
  772. auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
  773. case logAuctionNewClosedAuctionSlots:
  774. var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
  775. if err := c.contractAbi.UnpackIntoInterface(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
  776. return nil, nil, tracerr.Wrap(err)
  777. }
  778. auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
  779. case logAuctionNewOutbidding:
  780. var newOutbidding AuctionEventNewOutbidding
  781. if err := c.contractAbi.UnpackIntoInterface(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
  782. return nil, nil, tracerr.Wrap(err)
  783. }
  784. auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
  785. case logAuctionNewDonationAddress:
  786. var newDonationAddress AuctionEventNewDonationAddress
  787. newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  788. auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
  789. case logAuctionNewBootCoordinator:
  790. var newBootCoordinator AuctionEventNewBootCoordinator
  791. if err := c.contractAbi.UnpackIntoInterface(&newBootCoordinator, "NewBootCoordinator", vLog.Data); err != nil {
  792. return nil, nil, tracerr.Wrap(err)
  793. }
  794. newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  795. auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
  796. case logAuctionNewOpenAuctionSlots:
  797. var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
  798. if err := c.contractAbi.UnpackIntoInterface(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
  799. return nil, nil, tracerr.Wrap(err)
  800. }
  801. auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
  802. case logAuctionNewAllocationRatio:
  803. var newAllocationRatio AuctionEventNewAllocationRatio
  804. if err := c.contractAbi.UnpackIntoInterface(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
  805. return nil, nil, tracerr.Wrap(err)
  806. }
  807. auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
  808. case logAuctionSetCoordinator:
  809. var setCoordinator AuctionEventSetCoordinator
  810. if err := c.contractAbi.UnpackIntoInterface(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
  811. return nil, nil, tracerr.Wrap(err)
  812. }
  813. setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  814. setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  815. auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
  816. case logAuctionNewForgeAllocated:
  817. var newForgeAllocated AuctionEventNewForgeAllocated
  818. if err := c.contractAbi.UnpackIntoInterface(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
  819. return nil, nil, tracerr.Wrap(err)
  820. }
  821. newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  822. newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
  823. newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
  824. auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
  825. case logAuctionNewDefaultSlotSetBid:
  826. var auxNewDefaultSlotSetBid struct {
  827. SlotSet *big.Int
  828. NewInitialMinBid *big.Int
  829. }
  830. var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
  831. if err := c.contractAbi.UnpackIntoInterface(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
  832. return nil, nil, tracerr.Wrap(err)
  833. }
  834. newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
  835. newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
  836. auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
  837. case logAuctionNewForge:
  838. var newForge AuctionEventNewForge
  839. newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  840. newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
  841. auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
  842. case logAuctionHEZClaimed:
  843. var HEZClaimed AuctionEventHEZClaimed
  844. if err := c.contractAbi.UnpackIntoInterface(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
  845. return nil, nil, tracerr.Wrap(err)
  846. }
  847. HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  848. auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
  849. }
  850. }
  851. return &auctionEvents, blockHash, nil
  852. }