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.

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