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.

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