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.

1346 lines
39 KiB

  1. package test
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "encoding/json"
  6. "fmt"
  7. "math/big"
  8. "reflect"
  9. "sync"
  10. "time"
  11. "github.com/ethereum/go-ethereum"
  12. ethCommon "github.com/ethereum/go-ethereum/common"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/hermeznetwork/hermez-node/common"
  15. "github.com/hermeznetwork/hermez-node/eth"
  16. "github.com/hermeznetwork/hermez-node/log"
  17. "github.com/iden3/go-iden3-crypto/babyjub"
  18. "github.com/mitchellh/copystructure"
  19. )
  20. func init() {
  21. copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  22. func(raw interface{}) (interface{}, error) {
  23. in := raw.(big.Int)
  24. out := new(big.Int).Set(&in)
  25. return *out, nil
  26. }
  27. }
  28. // RollupBlock stores all the data related to the Rollup SC from an ethereum block
  29. type RollupBlock struct {
  30. State eth.RollupState
  31. Vars eth.RollupVariables
  32. Events eth.RollupEvents
  33. Txs map[ethCommon.Hash]*types.Transaction
  34. Constants *eth.RollupPublicConstants
  35. Eth *EthereumBlock
  36. }
  37. func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  38. txHash := tx.Hash()
  39. r.Txs[txHash] = tx
  40. return tx
  41. }
  42. var (
  43. errBidClosed = fmt.Errorf("Bid has already been closed")
  44. errBidNotOpen = fmt.Errorf("Bid has not been opened yet")
  45. errBidBelowMin = fmt.Errorf("Bid below minimum")
  46. errCoordNotReg = fmt.Errorf("Coordinator not registered")
  47. )
  48. // AuctionBlock stores all the data related to the Auction SC from an ethereum block
  49. type AuctionBlock struct {
  50. State eth.AuctionState
  51. Vars eth.AuctionVariables
  52. Events eth.AuctionEvents
  53. Txs map[ethCommon.Hash]*types.Transaction
  54. Constants *eth.AuctionConstants
  55. Eth *EthereumBlock
  56. }
  57. func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  58. txHash := tx.Hash()
  59. a.Txs[txHash] = tx
  60. return tx
  61. }
  62. func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  63. if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
  64. return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
  65. }
  66. return 0
  67. }
  68. func (a *AuctionBlock) getCurrentSlotNumber() int64 {
  69. return a.getSlotNumber(a.Eth.BlockNum)
  70. }
  71. func (a *AuctionBlock) getSlotSet(slot int64) int64 {
  72. return slot % int64(len(a.Vars.DefaultSlotSetBid))
  73. }
  74. func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
  75. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  76. return nil, errBidClosed
  77. }
  78. slotSet := a.getSlotSet(slot)
  79. // fmt.Println("slot:", slot, "slotSet:", slotSet)
  80. var prevBid *big.Int
  81. slotState, ok := a.State.Slots[slot]
  82. if !ok {
  83. slotState = eth.NewSlotState()
  84. a.State.Slots[slot] = slotState
  85. }
  86. // If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
  87. // bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
  88. if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
  89. prevBid = a.Vars.DefaultSlotSetBid[slotSet]
  90. } else {
  91. prevBid = slotState.BidAmount
  92. }
  93. outBid := new(big.Int).Set(prevBid)
  94. // fmt.Println("outBid:", outBid)
  95. outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
  96. outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
  97. outBid.Add(prevBid, outBid)
  98. // fmt.Println("minBid:", outBid)
  99. return outBid, nil
  100. }
  101. func (a *AuctionBlock) forge(forger ethCommon.Address) error {
  102. if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
  103. return err
  104. } else if !ok {
  105. return fmt.Errorf("Can't forge")
  106. }
  107. slotToForge := a.getSlotNumber(a.Eth.BlockNum)
  108. slotState, ok := a.State.Slots[slotToForge]
  109. if !ok {
  110. slotState = eth.NewSlotState()
  111. a.State.Slots[slotToForge] = slotState
  112. }
  113. slotState.Fulfilled = true
  114. a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
  115. Forger: forger,
  116. SlotToForge: slotToForge,
  117. })
  118. return nil
  119. }
  120. func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  121. if blockNum < a.Constants.GenesisBlockNum {
  122. return false, fmt.Errorf("Auction has not started yet")
  123. }
  124. slotToForge := a.getSlotNumber(blockNum)
  125. // Get the relativeBlock to check if the slotDeadline has been exceeded
  126. relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
  127. // If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
  128. // otherwise the one that has been saved will be used
  129. var minBid *big.Int
  130. slotState, ok := a.State.Slots[slotToForge]
  131. if !ok {
  132. slotState = eth.NewSlotState()
  133. a.State.Slots[slotToForge] = slotState
  134. }
  135. if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
  136. minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
  137. } else {
  138. minBid = slotState.ClosedMinBid
  139. }
  140. if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
  141. // if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
  142. return true, nil
  143. // TODO, find the forger set by the Bidder
  144. } else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
  145. coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
  146. // if forger bidAmount has exceeded the minBid it can forge
  147. return true, nil
  148. } else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
  149. // if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
  150. return true, nil
  151. } else {
  152. return false, nil
  153. }
  154. }
  155. // EthereumBlock stores all the generic data related to the an ethereum block
  156. type EthereumBlock struct {
  157. BlockNum int64
  158. Time int64
  159. Hash ethCommon.Hash
  160. ParentHash ethCommon.Hash
  161. Tokens map[ethCommon.Address]eth.ERC20Consts
  162. // state ethState
  163. }
  164. // Block represents a ethereum block
  165. type Block struct {
  166. Rollup *RollupBlock
  167. Auction *AuctionBlock
  168. Eth *EthereumBlock
  169. }
  170. func (b *Block) copy() *Block {
  171. bCopyRaw, err := copystructure.Copy(b)
  172. if err != nil {
  173. panic(err)
  174. }
  175. bCopy := bCopyRaw.(*Block)
  176. return bCopy
  177. }
  178. // Next prepares the successive block.
  179. func (b *Block) Next() *Block {
  180. blockNext := b.copy()
  181. blockNext.Rollup.Events = eth.NewRollupEvents()
  182. blockNext.Auction.Events = eth.NewAuctionEvents()
  183. blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
  184. blockNext.Eth.ParentHash = b.Eth.Hash
  185. blockNext.Rollup.Constants = b.Rollup.Constants
  186. blockNext.Auction.Constants = b.Auction.Constants
  187. blockNext.Rollup.Eth = blockNext.Eth
  188. blockNext.Auction.Eth = blockNext.Eth
  189. return blockNext
  190. }
  191. // ClientSetup is used to initialize the constants of the Smart Contracts and
  192. // other details of the test Client
  193. type ClientSetup struct {
  194. RollupConstants *eth.RollupPublicConstants
  195. RollupVariables *eth.RollupVariables
  196. AuctionConstants *eth.AuctionConstants
  197. AuctionVariables *eth.AuctionVariables
  198. VerifyProof bool
  199. }
  200. // NewClientSetupExample returns a ClientSetup example with hardcoded realistic
  201. // values. With this setup, the rollup genesis will be block 1, and block 0
  202. // and 1 will be premined.
  203. //nolint:gomnd
  204. func NewClientSetupExample() *ClientSetup {
  205. // rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
  206. // if !ok {
  207. // panic("bad rfield")
  208. // }
  209. initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
  210. if !ok {
  211. panic("bad initialMinimalBidding")
  212. }
  213. tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
  214. governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
  215. rollupConstants := &eth.RollupPublicConstants{
  216. Verifiers: []eth.RollupVerifierStruct{
  217. {
  218. MaxTx: 2048,
  219. NLevels: 32,
  220. },
  221. },
  222. TokenHEZ: tokenHEZ,
  223. HermezGovernanceDAOAddress: governanceAddress,
  224. SafetyAddress: ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
  225. HermezAuctionContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
  226. WithdrawDelayerContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
  227. }
  228. rollupVariables := &eth.RollupVariables{
  229. FeeAddToken: big.NewInt(11),
  230. ForgeL1L2BatchTimeout: 9,
  231. WithdrawalDelay: 80,
  232. }
  233. auctionConstants := &eth.AuctionConstants{
  234. BlocksPerSlot: 40,
  235. InitialMinimalBidding: initialMinimalBidding,
  236. GenesisBlockNum: 1,
  237. GovernanceAddress: governanceAddress,
  238. TokenHEZ: tokenHEZ,
  239. HermezRollup: ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
  240. }
  241. auctionVariables := &eth.AuctionVariables{
  242. DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
  243. BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
  244. DefaultSlotSetBid: [6]*big.Int{
  245. big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
  246. big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
  247. ClosedAuctionSlots: 2,
  248. OpenAuctionSlots: 4320,
  249. AllocationRatio: [3]uint16{4000, 4000, 2000},
  250. Outbidding: 1000,
  251. SlotDeadline: 20,
  252. }
  253. return &ClientSetup{
  254. RollupConstants: rollupConstants,
  255. RollupVariables: rollupVariables,
  256. AuctionConstants: auctionConstants,
  257. AuctionVariables: auctionVariables,
  258. }
  259. }
  260. // Timer is an interface to simulate a source of time, useful to advance time
  261. // virtually.
  262. type Timer interface {
  263. Time() int64
  264. }
  265. // type forgeBatchArgs struct {
  266. // ethTx *types.Transaction
  267. // blockNum int64
  268. // blockHash ethCommon.Hash
  269. // }
  270. type batch struct {
  271. ForgeBatchArgs eth.RollupForgeBatchArgs
  272. Sender ethCommon.Address
  273. }
  274. // Client implements the eth.ClientInterface interface, allowing to manipulate the
  275. // values for testing, working with deterministic results.
  276. type Client struct {
  277. rw *sync.RWMutex
  278. log bool
  279. addr *ethCommon.Address
  280. rollupConstants *eth.RollupPublicConstants
  281. auctionConstants *eth.AuctionConstants
  282. blocks map[int64]*Block
  283. // state state
  284. blockNum int64 // last mined block num
  285. maxBlockNum int64 // highest block num calculated
  286. timer Timer
  287. hasher hasher
  288. forgeBatchArgsPending map[ethCommon.Hash]*batch
  289. forgeBatchArgs map[ethCommon.Hash]*batch
  290. }
  291. // NewClient returns a new test Client that implements the eth.IClient
  292. // interface, at the given initialBlockNumber.
  293. func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
  294. blocks := make(map[int64]*Block)
  295. blockNum := int64(0)
  296. hasher := hasher{}
  297. // Add ethereum genesis block
  298. mapL1TxQueue := make(map[int64]*eth.QueueStruct)
  299. mapL1TxQueue[0] = eth.NewQueueStruct()
  300. mapL1TxQueue[1] = eth.NewQueueStruct()
  301. blockCurrent := &Block{
  302. Rollup: &RollupBlock{
  303. State: eth.RollupState{
  304. StateRoot: big.NewInt(0),
  305. ExitRoots: make([]*big.Int, 0),
  306. ExitNullifierMap: make(map[[256 / 8]byte]bool),
  307. // TokenID = 0 is ETH. Set first entry in TokenList with 0x0 address for ETH.
  308. TokenList: []ethCommon.Address{{}},
  309. TokenMap: make(map[ethCommon.Address]bool),
  310. MapL1TxQueue: mapL1TxQueue,
  311. LastL1L2Batch: 0,
  312. CurrentToForgeL1TxsNum: 0,
  313. LastToForgeL1TxsNum: 1,
  314. CurrentIdx: 0,
  315. },
  316. Vars: *setup.RollupVariables,
  317. Txs: make(map[ethCommon.Hash]*types.Transaction),
  318. Events: eth.NewRollupEvents(),
  319. Constants: setup.RollupConstants,
  320. },
  321. Auction: &AuctionBlock{
  322. State: eth.AuctionState{
  323. Slots: make(map[int64]*eth.SlotState),
  324. PendingBalances: make(map[ethCommon.Address]*big.Int),
  325. Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
  326. },
  327. Vars: *setup.AuctionVariables,
  328. Txs: make(map[ethCommon.Hash]*types.Transaction),
  329. Events: eth.NewAuctionEvents(),
  330. Constants: setup.AuctionConstants,
  331. },
  332. Eth: &EthereumBlock{
  333. BlockNum: blockNum,
  334. Time: timer.Time(),
  335. Hash: hasher.Next(),
  336. ParentHash: ethCommon.Hash{},
  337. Tokens: make(map[ethCommon.Address]eth.ERC20Consts),
  338. },
  339. }
  340. blockCurrent.Rollup.Eth = blockCurrent.Eth
  341. blockCurrent.Auction.Eth = blockCurrent.Eth
  342. blocks[blockNum] = blockCurrent
  343. blockNext := blockCurrent.Next()
  344. blocks[blockNum+1] = blockNext
  345. c := Client{
  346. rw: &sync.RWMutex{},
  347. log: l,
  348. addr: addr,
  349. rollupConstants: setup.RollupConstants,
  350. auctionConstants: setup.AuctionConstants,
  351. blocks: blocks,
  352. timer: timer,
  353. hasher: hasher,
  354. forgeBatchArgsPending: make(map[ethCommon.Hash]*batch),
  355. forgeBatchArgs: make(map[ethCommon.Hash]*batch),
  356. blockNum: blockNum,
  357. maxBlockNum: blockNum,
  358. }
  359. for i := int64(1); i < setup.AuctionConstants.GenesisBlockNum+1; i++ {
  360. c.CtlMineBlock()
  361. }
  362. return &c
  363. }
  364. //
  365. // Mock Control
  366. //
  367. func (c *Client) setNextBlock(block *Block) {
  368. c.blocks[c.blockNum+1] = block
  369. }
  370. func (c *Client) revertIfErr(err error, block *Block) {
  371. if err != nil {
  372. log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
  373. c.setNextBlock(block)
  374. }
  375. }
  376. // Debugf calls log.Debugf if c.log is true
  377. func (c *Client) Debugf(template string, args ...interface{}) {
  378. if c.log {
  379. log.Debugf(template, args...)
  380. }
  381. }
  382. // Debugw calls log.Debugw if c.log is true
  383. func (c *Client) Debugw(template string, kv ...interface{}) {
  384. if c.log {
  385. log.Debugw(template, kv...)
  386. }
  387. }
  388. type hasher struct {
  389. counter uint64
  390. }
  391. // Next returns the next hash
  392. func (h *hasher) Next() ethCommon.Hash {
  393. var hash ethCommon.Hash
  394. binary.LittleEndian.PutUint64(hash[:], h.counter)
  395. h.counter++
  396. return hash
  397. }
  398. func (c *Client) nextBlock() *Block {
  399. return c.blocks[c.blockNum+1]
  400. }
  401. func (c *Client) currentBlock() *Block {
  402. return c.blocks[c.blockNum]
  403. }
  404. // CtlSetAddr sets the address of the client
  405. func (c *Client) CtlSetAddr(addr ethCommon.Address) {
  406. c.addr = &addr
  407. }
  408. // CtlMineBlock moves one block forward
  409. func (c *Client) CtlMineBlock() {
  410. c.rw.Lock()
  411. defer c.rw.Unlock()
  412. blockCurrent := c.nextBlock()
  413. c.blockNum++
  414. c.maxBlockNum = c.blockNum
  415. blockCurrent.Eth.Time = c.timer.Time()
  416. blockCurrent.Eth.Hash = c.hasher.Next()
  417. for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
  418. c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
  419. }
  420. c.forgeBatchArgsPending = make(map[ethCommon.Hash]*batch)
  421. blockNext := blockCurrent.Next()
  422. c.blocks[c.blockNum+1] = blockNext
  423. c.Debugw("TestClient mined block", "blockNum", c.blockNum)
  424. }
  425. // CtlRollback discards the last mined block. Use this to replace a mined
  426. // block to simulate reorgs.
  427. func (c *Client) CtlRollback() {
  428. c.rw.Lock()
  429. defer c.rw.Unlock()
  430. if c.blockNum == 0 {
  431. panic("Can't rollback at blockNum = 0")
  432. }
  433. delete(c.blocks, c.blockNum+1) // delete next block
  434. delete(c.blocks, c.blockNum) // delete current block
  435. c.blockNum--
  436. blockCurrent := c.blocks[c.blockNum]
  437. blockNext := blockCurrent.Next()
  438. c.blocks[c.blockNum+1] = blockNext
  439. }
  440. //
  441. // Ethereum
  442. //
  443. // EthCurrentBlock returns the current blockNum
  444. func (c *Client) EthCurrentBlock() (int64, error) {
  445. c.rw.RLock()
  446. defer c.rw.RUnlock()
  447. if c.blockNum < c.maxBlockNum {
  448. panic("blockNum has decreased. " +
  449. "After a rollback you must mine to reach the same or higher blockNum")
  450. }
  451. return c.blockNum, nil
  452. }
  453. // EthTransactionReceipt returns the transaction receipt of the given txHash
  454. func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
  455. c.rw.RLock()
  456. defer c.rw.RUnlock()
  457. for i := int64(0); i < c.blockNum; i++ {
  458. b := c.blocks[i]
  459. _, ok := b.Rollup.Txs[txHash]
  460. if !ok {
  461. _, ok = b.Auction.Txs[txHash]
  462. }
  463. if ok {
  464. return &types.Receipt{
  465. TxHash: txHash,
  466. Status: types.ReceiptStatusSuccessful,
  467. BlockHash: b.Eth.Hash,
  468. BlockNumber: big.NewInt(b.Eth.BlockNum),
  469. }, nil
  470. }
  471. }
  472. return nil, nil
  473. }
  474. // CtlAddERC20 adds an ERC20 token to the blockchain.
  475. func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
  476. nextBlock := c.nextBlock()
  477. e := nextBlock.Eth
  478. e.Tokens[tokenAddr] = constants
  479. }
  480. // EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
  481. func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
  482. currentBlock := c.currentBlock()
  483. e := currentBlock.Eth
  484. if constants, ok := e.Tokens[tokenAddr]; ok {
  485. return &constants, nil
  486. }
  487. return nil, fmt.Errorf("tokenAddr not found")
  488. }
  489. // func newHeader(number *big.Int) *types.Header {
  490. // return &types.Header{
  491. // Number: number,
  492. // Time: uint64(number.Int64()),
  493. // }
  494. // }
  495. // EthHeaderByNumber returns the *types.Header for the given block number in a
  496. // deterministic way.
  497. // func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
  498. // return newHeader(number), nil
  499. // }
  500. // EthBlockByNumber returns the *common.Block for the given block number in a
  501. // deterministic way.
  502. func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
  503. c.rw.RLock()
  504. defer c.rw.RUnlock()
  505. if blockNum > c.blockNum {
  506. return nil, ethereum.NotFound
  507. }
  508. block := c.blocks[blockNum]
  509. return &common.Block{
  510. EthBlockNum: blockNum,
  511. Timestamp: time.Unix(block.Eth.Time, 0),
  512. Hash: block.Eth.Hash,
  513. ParentHash: block.Eth.ParentHash,
  514. }, nil
  515. }
  516. // EthAddress returns the ethereum address of the account loaded into the Client
  517. func (c *Client) EthAddress() (*ethCommon.Address, error) {
  518. if c.addr == nil {
  519. return nil, eth.ErrAccountNil
  520. }
  521. return c.addr, nil
  522. }
  523. var errTODO = fmt.Errorf("TODO: Not implemented yet")
  524. //
  525. // Rollup
  526. //
  527. // CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
  528. // func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
  529. // c.rw.Lock()
  530. // defer c.rw.Unlock()
  531. //
  532. // nextBlock := c.nextBlock()
  533. // r := nextBlock.Rollup
  534. // queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  535. // if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
  536. // r.State.LastToForgeL1TxsNum++
  537. // r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  538. // queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  539. // }
  540. // if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
  541. // panic("l1Tx.FromIdx > r.State.CurrentIdx")
  542. // }
  543. // if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
  544. // panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  545. // }
  546. // queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  547. // r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  548. // L1Tx: *l1Tx,
  549. // ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
  550. // Position: len(queue.L1TxQueue) - 1,
  551. // })
  552. // }
  553. // RollupL1UserTxERC20Permit is the interface to call the smart contract function
  554. func (c *Client) RollupL1UserTxERC20Permit(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64, deadline *big.Int) (tx *types.Transaction, err error) {
  555. log.Error("TODO")
  556. return nil, errTODO
  557. }
  558. // RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
  559. func (c *Client) RollupL1UserTxERC20ETH(
  560. fromBJJ *babyjub.PublicKey,
  561. fromIdx int64,
  562. loadAmount *big.Int,
  563. amount *big.Int,
  564. tokenID uint32,
  565. toIdx int64,
  566. ) (tx *types.Transaction, err error) {
  567. c.rw.Lock()
  568. defer c.rw.Unlock()
  569. cpy := c.nextBlock().copy()
  570. defer func() { c.revertIfErr(err, cpy) }()
  571. _, err = common.NewFloat16(amount)
  572. if err != nil {
  573. return nil, err
  574. }
  575. _, err = common.NewFloat16(loadAmount)
  576. if err != nil {
  577. return nil, err
  578. }
  579. nextBlock := c.nextBlock()
  580. r := nextBlock.Rollup
  581. queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  582. if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
  583. r.State.LastToForgeL1TxsNum++
  584. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  585. queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  586. }
  587. if fromIdx > r.State.CurrentIdx {
  588. panic("l1Tx.FromIdx > r.State.CurrentIdx")
  589. }
  590. if int(tokenID)+1 > len(r.State.TokenList) {
  591. panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  592. }
  593. toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
  594. l1Tx, err := common.NewL1Tx(&common.L1Tx{
  595. FromIdx: common.Idx(fromIdx),
  596. FromEthAddr: *c.addr,
  597. FromBJJ: fromBJJ,
  598. Amount: amount,
  599. LoadAmount: loadAmount,
  600. TokenID: common.TokenID(tokenID),
  601. ToIdx: common.Idx(toIdx),
  602. ToForgeL1TxsNum: &toForgeL1TxsNum,
  603. Position: len(queue.L1TxQueue),
  604. UserOrigin: true,
  605. })
  606. if err != nil {
  607. return nil, err
  608. }
  609. queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  610. r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  611. L1UserTx: *l1Tx,
  612. })
  613. return r.addTransaction(newTransaction("l1UserTxERC20ETH", l1Tx)), nil
  614. }
  615. // RollupL1UserTxERC777 is the interface to call the smart contract function
  616. // func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
  617. // log.Error("TODO")
  618. // return nil, errTODO
  619. // }
  620. // RollupRegisterTokensCount is the interface to call the smart contract function
  621. func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
  622. log.Error("TODO")
  623. return nil, errTODO
  624. }
  625. // RollupWithdrawCircuit is the interface to call the smart contract function
  626. func (c *Client) RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int, tokenID uint32, numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction, error) {
  627. log.Error("TODO")
  628. return nil, errTODO
  629. }
  630. // RollupWithdrawMerkleProof is the interface to call the smart contract function
  631. func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error) {
  632. log.Error("TODO")
  633. return nil, errTODO
  634. }
  635. type transactionData struct {
  636. Name string
  637. Value interface{}
  638. }
  639. func newTransaction(name string, value interface{}) *types.Transaction {
  640. data, err := json.Marshal(transactionData{name, value})
  641. if err != nil {
  642. panic(err)
  643. }
  644. return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
  645. data)
  646. }
  647. // RollupForgeBatch is the interface to call the smart contract function
  648. func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
  649. c.rw.Lock()
  650. defer c.rw.Unlock()
  651. cpy := c.nextBlock().copy()
  652. defer func() { c.revertIfErr(err, cpy) }()
  653. if c.addr == nil {
  654. return nil, eth.ErrAccountNil
  655. }
  656. a := c.nextBlock().Auction
  657. ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
  658. if err != nil {
  659. return nil, err
  660. }
  661. if !ok {
  662. return nil, fmt.Errorf("incorrect slot")
  663. }
  664. // TODO: Verify proof
  665. // Auction
  666. err = a.forge(*c.addr)
  667. if err != nil {
  668. return nil, err
  669. }
  670. // TODO: If successful, store the tx in a successful array.
  671. // TODO: If failed, store the tx in a failed array.
  672. // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
  673. return c.addBatch(args)
  674. }
  675. // CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
  676. func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
  677. c.rw.Lock()
  678. defer c.rw.Unlock()
  679. if _, err := c.addBatch(args); err != nil {
  680. panic(err)
  681. }
  682. }
  683. func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
  684. nextBlock := c.nextBlock()
  685. r := nextBlock.Rollup
  686. r.State.StateRoot = args.NewStRoot
  687. if args.NewLastIdx < r.State.CurrentIdx {
  688. return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
  689. }
  690. r.State.CurrentIdx = args.NewLastIdx
  691. r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
  692. if args.L1Batch {
  693. r.State.CurrentToForgeL1TxsNum++
  694. if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
  695. r.State.LastToForgeL1TxsNum++
  696. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  697. }
  698. }
  699. ethTx := r.addTransaction(newTransaction("forgebatch", args))
  700. c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
  701. r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
  702. BatchNum: int64(len(r.State.ExitRoots)),
  703. EthTxHash: ethTx.Hash(),
  704. })
  705. return ethTx, nil
  706. }
  707. // RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
  708. // sets `deadlie`.
  709. func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
  710. return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
  711. }
  712. // RollupAddToken is the interface to call the smart contract function
  713. func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
  714. deadline *big.Int) (tx *types.Transaction, err error) {
  715. c.rw.Lock()
  716. defer c.rw.Unlock()
  717. cpy := c.nextBlock().copy()
  718. defer func() { c.revertIfErr(err, cpy) }()
  719. if c.addr == nil {
  720. return nil, eth.ErrAccountNil
  721. }
  722. nextBlock := c.nextBlock()
  723. r := nextBlock.Rollup
  724. if _, ok := r.State.TokenMap[tokenAddress]; ok {
  725. return nil, fmt.Errorf("Token %v already registered", tokenAddress)
  726. }
  727. if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
  728. return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken)
  729. }
  730. r.State.TokenMap[tokenAddress] = true
  731. r.State.TokenList = append(r.State.TokenList, tokenAddress)
  732. r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
  733. TokenID: uint32(len(r.State.TokenList) - 1)})
  734. return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
  735. }
  736. // RollupGetCurrentTokens is the interface to call the smart contract function
  737. func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
  738. c.rw.RLock()
  739. defer c.rw.RUnlock()
  740. log.Error("TODO")
  741. return nil, errTODO
  742. }
  743. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  744. func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
  745. c.rw.Lock()
  746. defer c.rw.Unlock()
  747. cpy := c.nextBlock().copy()
  748. defer func() { c.revertIfErr(err, cpy) }()
  749. if c.addr == nil {
  750. return nil, eth.ErrAccountNil
  751. }
  752. log.Error("TODO")
  753. return nil, errTODO
  754. }
  755. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  756. func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  757. c.rw.Lock()
  758. defer c.rw.Unlock()
  759. cpy := c.nextBlock().copy()
  760. defer func() { c.revertIfErr(err, cpy) }()
  761. if c.addr == nil {
  762. return nil, eth.ErrAccountNil
  763. }
  764. log.Error("TODO")
  765. return nil, errTODO
  766. }
  767. // RollupUpdateTokensHEZ is the interface to call the smart contract function
  768. // func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
  769. // c.rw.Lock()
  770. // defer c.rw.Unlock()
  771. // cpy := c.nextBlock().copy()
  772. // defer func() { c.revertIfErr(err, cpy) }()
  773. //
  774. // log.Error("TODO")
  775. // return nil, errTODO
  776. // }
  777. // RollupUpdateGovernance is the interface to call the smart contract function
  778. // func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  779. // return nil, errTODO
  780. // }
  781. // RollupConstants returns the Constants of the Rollup Smart Contract
  782. func (c *Client) RollupConstants() (*eth.RollupPublicConstants, error) {
  783. c.rw.RLock()
  784. defer c.rw.RUnlock()
  785. log.Error("TODO")
  786. return nil, errTODO
  787. }
  788. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  789. func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
  790. c.rw.RLock()
  791. defer c.rw.RUnlock()
  792. block, ok := c.blocks[blockNum]
  793. if !ok {
  794. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  795. }
  796. return &block.Rollup.Events, &block.Eth.Hash, nil
  797. }
  798. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
  799. func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
  800. c.rw.RLock()
  801. defer c.rw.RUnlock()
  802. batch, ok := c.forgeBatchArgs[ethTxHash]
  803. if !ok {
  804. return nil, nil, fmt.Errorf("transaction not found")
  805. }
  806. return &batch.ForgeBatchArgs, &batch.Sender, nil
  807. }
  808. //
  809. // Auction
  810. //
  811. // AuctionSetSlotDeadline is the interface to call the smart contract function
  812. func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
  813. c.rw.Lock()
  814. defer c.rw.Unlock()
  815. cpy := c.nextBlock().copy()
  816. defer func() { c.revertIfErr(err, cpy) }()
  817. if c.addr == nil {
  818. return nil, eth.ErrAccountNil
  819. }
  820. log.Error("TODO")
  821. return nil, errTODO
  822. }
  823. // AuctionGetSlotDeadline is the interface to call the smart contract function
  824. func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
  825. c.rw.RLock()
  826. defer c.rw.RUnlock()
  827. log.Error("TODO")
  828. return 0, errTODO
  829. }
  830. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  831. func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  832. c.rw.Lock()
  833. defer c.rw.Unlock()
  834. cpy := c.nextBlock().copy()
  835. defer func() { c.revertIfErr(err, cpy) }()
  836. if c.addr == nil {
  837. return nil, eth.ErrAccountNil
  838. }
  839. log.Error("TODO")
  840. return nil, errTODO
  841. }
  842. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  843. func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
  844. c.rw.RLock()
  845. defer c.rw.RUnlock()
  846. log.Error("TODO")
  847. return 0, errTODO
  848. }
  849. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  850. func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  851. c.rw.Lock()
  852. defer c.rw.Unlock()
  853. cpy := c.nextBlock().copy()
  854. defer func() { c.revertIfErr(err, cpy) }()
  855. if c.addr == nil {
  856. return nil, eth.ErrAccountNil
  857. }
  858. log.Error("TODO")
  859. return nil, errTODO
  860. }
  861. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  862. func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
  863. c.rw.RLock()
  864. defer c.rw.RUnlock()
  865. log.Error("TODO")
  866. return 0, errTODO
  867. }
  868. // AuctionSetOutbidding is the interface to call the smart contract function
  869. func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  870. c.rw.Lock()
  871. defer c.rw.Unlock()
  872. cpy := c.nextBlock().copy()
  873. defer func() { c.revertIfErr(err, cpy) }()
  874. if c.addr == nil {
  875. return nil, eth.ErrAccountNil
  876. }
  877. log.Error("TODO")
  878. return nil, errTODO
  879. }
  880. // AuctionGetOutbidding is the interface to call the smart contract function
  881. func (c *Client) AuctionGetOutbidding() (uint16, error) {
  882. c.rw.RLock()
  883. defer c.rw.RUnlock()
  884. log.Error("TODO")
  885. return 0, errTODO
  886. }
  887. // AuctionSetAllocationRatio is the interface to call the smart contract function
  888. func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  889. c.rw.Lock()
  890. defer c.rw.Unlock()
  891. cpy := c.nextBlock().copy()
  892. defer func() { c.revertIfErr(err, cpy) }()
  893. if c.addr == nil {
  894. return nil, eth.ErrAccountNil
  895. }
  896. log.Error("TODO")
  897. return nil, errTODO
  898. }
  899. // AuctionGetAllocationRatio is the interface to call the smart contract function
  900. func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
  901. c.rw.RLock()
  902. defer c.rw.RUnlock()
  903. log.Error("TODO")
  904. return [3]uint16{}, errTODO
  905. }
  906. // AuctionSetDonationAddress is the interface to call the smart contract function
  907. func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  908. c.rw.Lock()
  909. defer c.rw.Unlock()
  910. cpy := c.nextBlock().copy()
  911. defer func() { c.revertIfErr(err, cpy) }()
  912. if c.addr == nil {
  913. return nil, eth.ErrAccountNil
  914. }
  915. log.Error("TODO")
  916. return nil, errTODO
  917. }
  918. // AuctionGetDonationAddress is the interface to call the smart contract function
  919. func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
  920. c.rw.RLock()
  921. defer c.rw.RUnlock()
  922. log.Error("TODO")
  923. return nil, errTODO
  924. }
  925. // AuctionSetBootCoordinator is the interface to call the smart contract function
  926. func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
  927. c.rw.Lock()
  928. defer c.rw.Unlock()
  929. cpy := c.nextBlock().copy()
  930. defer func() { c.revertIfErr(err, cpy) }()
  931. if c.addr == nil {
  932. return nil, eth.ErrAccountNil
  933. }
  934. log.Error("TODO")
  935. return nil, errTODO
  936. }
  937. // AuctionGetBootCoordinator is the interface to call the smart contract function
  938. func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
  939. c.rw.RLock()
  940. defer c.rw.RUnlock()
  941. currentBlock := c.currentBlock()
  942. a := currentBlock.Auction
  943. return &a.Vars.BootCoordinator, nil
  944. }
  945. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  946. func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  947. c.rw.Lock()
  948. defer c.rw.Unlock()
  949. cpy := c.nextBlock().copy()
  950. defer func() { c.revertIfErr(err, cpy) }()
  951. if c.addr == nil {
  952. return nil, eth.ErrAccountNil
  953. }
  954. log.Error("TODO")
  955. return nil, errTODO
  956. }
  957. // AuctionSetCoordinator is the interface to call the smart contract function
  958. func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
  959. c.rw.Lock()
  960. defer c.rw.Unlock()
  961. cpy := c.nextBlock().copy()
  962. defer func() { c.revertIfErr(err, cpy) }()
  963. if c.addr == nil {
  964. return nil, eth.ErrAccountNil
  965. }
  966. nextBlock := c.nextBlock()
  967. a := nextBlock.Auction
  968. a.State.Coordinators[*c.addr] = &eth.Coordinator{
  969. Forger: forger,
  970. URL: URL,
  971. }
  972. a.Events.SetCoordinator = append(a.Events.SetCoordinator,
  973. eth.AuctionEventSetCoordinator{
  974. BidderAddress: *c.addr,
  975. ForgerAddress: forger,
  976. CoordinatorURL: URL,
  977. })
  978. type data struct {
  979. BidderAddress ethCommon.Address
  980. ForgerAddress ethCommon.Address
  981. URL string
  982. }
  983. return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
  984. }
  985. // AuctionIsRegisteredCoordinator is the interface to call the smart contract function
  986. func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
  987. c.rw.RLock()
  988. defer c.rw.RUnlock()
  989. log.Error("TODO")
  990. return false, errTODO
  991. }
  992. // AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
  993. func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
  994. c.rw.Lock()
  995. defer c.rw.Unlock()
  996. cpy := c.nextBlock().copy()
  997. defer func() { c.revertIfErr(err, cpy) }()
  998. if c.addr == nil {
  999. return nil, eth.ErrAccountNil
  1000. }
  1001. log.Error("TODO")
  1002. return nil, errTODO
  1003. }
  1004. // AuctionGetSlotNumber is the interface to call the smart contract function
  1005. func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
  1006. c.rw.RLock()
  1007. defer c.rw.RUnlock()
  1008. currentBlock := c.currentBlock()
  1009. a := currentBlock.Auction
  1010. return a.getSlotNumber(blockNum), nil
  1011. }
  1012. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  1013. func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
  1014. c.rw.RLock()
  1015. defer c.rw.RUnlock()
  1016. log.Error("TODO")
  1017. return 0, errTODO
  1018. }
  1019. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  1020. func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
  1021. c.rw.RLock()
  1022. defer c.rw.RUnlock()
  1023. log.Error("TODO")
  1024. return nil, errTODO
  1025. }
  1026. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  1027. func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
  1028. c.rw.RLock()
  1029. defer c.rw.RUnlock()
  1030. log.Error("TODO")
  1031. return nil, errTODO
  1032. }
  1033. // AuctionGetSlotSet is the interface to call the smart contract function
  1034. func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
  1035. c.rw.RLock()
  1036. defer c.rw.RUnlock()
  1037. log.Error("TODO")
  1038. return nil, errTODO
  1039. }
  1040. // AuctionTokensReceived is the interface to call the smart contract function
  1041. // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
  1042. // return errTODO
  1043. // }
  1044. // AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
  1045. func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
  1046. return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
  1047. }
  1048. // AuctionBid is the interface to call the smart contract function. This
  1049. // implementation behaves as if any address has infinite tokens.
  1050. func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
  1051. deadline *big.Int) (tx *types.Transaction, err error) {
  1052. c.rw.Lock()
  1053. defer c.rw.Unlock()
  1054. cpy := c.nextBlock().copy()
  1055. defer func() { func() { c.revertIfErr(err, cpy) }() }()
  1056. if c.addr == nil {
  1057. return nil, eth.ErrAccountNil
  1058. }
  1059. nextBlock := c.nextBlock()
  1060. a := nextBlock.Auction
  1061. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  1062. return nil, errBidClosed
  1063. }
  1064. if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
  1065. return nil, errBidNotOpen
  1066. }
  1067. minBid, err := a.getMinBidBySlot(slot)
  1068. if err != nil {
  1069. return nil, err
  1070. }
  1071. if bidAmount.Cmp(minBid) == -1 {
  1072. return nil, errBidBelowMin
  1073. }
  1074. if _, ok := a.State.Coordinators[*c.addr]; !ok {
  1075. return nil, errCoordNotReg
  1076. }
  1077. slotState, ok := a.State.Slots[slot]
  1078. if !ok {
  1079. slotState = eth.NewSlotState()
  1080. a.State.Slots[slot] = slotState
  1081. }
  1082. slotState.Bidder = *c.addr
  1083. slotState.BidAmount = bidAmount
  1084. a.Events.NewBid = append(a.Events.NewBid,
  1085. eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
  1086. type data struct {
  1087. Slot int64
  1088. BidAmount *big.Int
  1089. Bidder ethCommon.Address
  1090. }
  1091. return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
  1092. }
  1093. // AuctionMultiBid is the interface to call the smart contract function. This
  1094. // implementation behaves as if any address has infinite tokens.
  1095. func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64, slotSet [6]bool,
  1096. maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
  1097. c.rw.Lock()
  1098. defer c.rw.Unlock()
  1099. cpy := c.nextBlock().copy()
  1100. defer func() { c.revertIfErr(err, cpy) }()
  1101. if c.addr == nil {
  1102. return nil, eth.ErrAccountNil
  1103. }
  1104. log.Error("TODO")
  1105. return nil, errTODO
  1106. }
  1107. // AuctionCanForge is the interface to call the smart contract function
  1108. func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  1109. c.rw.RLock()
  1110. defer c.rw.RUnlock()
  1111. currentBlock := c.currentBlock()
  1112. a := currentBlock.Auction
  1113. return a.canForge(forger, blockNum)
  1114. }
  1115. // AuctionForge is the interface to call the smart contract function
  1116. func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  1117. c.rw.Lock()
  1118. defer c.rw.Unlock()
  1119. cpy := c.nextBlock().copy()
  1120. defer func() { c.revertIfErr(err, cpy) }()
  1121. if c.addr == nil {
  1122. return nil, eth.ErrAccountNil
  1123. }
  1124. log.Error("TODO")
  1125. return nil, errTODO
  1126. }
  1127. // AuctionClaimHEZ is the interface to call the smart contract function
  1128. func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  1129. c.rw.Lock()
  1130. defer c.rw.Unlock()
  1131. cpy := c.nextBlock().copy()
  1132. defer func() { c.revertIfErr(err, cpy) }()
  1133. if c.addr == nil {
  1134. return nil, eth.ErrAccountNil
  1135. }
  1136. log.Error("TODO")
  1137. return nil, errTODO
  1138. }
  1139. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  1140. func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
  1141. c.rw.RLock()
  1142. defer c.rw.RUnlock()
  1143. log.Error("TODO")
  1144. return nil, errTODO
  1145. }
  1146. // AuctionConstants returns the Constants of the Auction Smart Contract
  1147. func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
  1148. c.rw.RLock()
  1149. defer c.rw.RUnlock()
  1150. return c.auctionConstants, nil
  1151. }
  1152. // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
  1153. func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
  1154. c.rw.RLock()
  1155. defer c.rw.RUnlock()
  1156. block, ok := c.blocks[blockNum]
  1157. if !ok {
  1158. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  1159. }
  1160. return &block.Auction.Events, &block.Eth.Hash, nil
  1161. }