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.

1324 lines
38 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. // RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
  554. func (c *Client) RollupL1UserTxERC20ETH(
  555. fromBJJ *babyjub.PublicKey,
  556. fromIdx int64,
  557. loadAmount *big.Int,
  558. amount *big.Int,
  559. tokenID uint32,
  560. toIdx int64,
  561. ) (tx *types.Transaction, err error) {
  562. c.rw.Lock()
  563. defer c.rw.Unlock()
  564. cpy := c.nextBlock().copy()
  565. defer func() { c.revertIfErr(err, cpy) }()
  566. _, err = common.NewFloat16(amount)
  567. if err != nil {
  568. return nil, err
  569. }
  570. _, err = common.NewFloat16(loadAmount)
  571. if err != nil {
  572. return nil, err
  573. }
  574. nextBlock := c.nextBlock()
  575. r := nextBlock.Rollup
  576. queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  577. if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
  578. r.State.LastToForgeL1TxsNum++
  579. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  580. queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
  581. }
  582. if fromIdx > r.State.CurrentIdx {
  583. panic("l1Tx.FromIdx > r.State.CurrentIdx")
  584. }
  585. if int(tokenID)+1 > len(r.State.TokenList) {
  586. panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
  587. }
  588. toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
  589. l1Tx, err := common.NewL1Tx(&common.L1Tx{
  590. FromIdx: common.Idx(fromIdx),
  591. FromEthAddr: *c.addr,
  592. FromBJJ: fromBJJ,
  593. Amount: amount,
  594. LoadAmount: loadAmount,
  595. TokenID: common.TokenID(tokenID),
  596. ToIdx: common.Idx(toIdx),
  597. ToForgeL1TxsNum: &toForgeL1TxsNum,
  598. Position: len(queue.L1TxQueue) - 1,
  599. UserOrigin: true,
  600. })
  601. if err != nil {
  602. return nil, err
  603. }
  604. queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
  605. r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
  606. L1UserTx: *l1Tx,
  607. })
  608. return r.addTransaction(newTransaction("l1UserTxERC20ETH", l1Tx)), nil
  609. }
  610. // RollupL1UserTxERC777 is the interface to call the smart contract function
  611. func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
  612. log.Error("TODO")
  613. return nil, errTODO
  614. }
  615. // RollupRegisterTokensCount is the interface to call the smart contract function
  616. func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
  617. log.Error("TODO")
  618. return nil, errTODO
  619. }
  620. // RollupWithdrawCircuit is the interface to call the smart contract function
  621. 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) {
  622. log.Error("TODO")
  623. return nil, errTODO
  624. }
  625. // RollupWithdrawMerkleProof is the interface to call the smart contract function
  626. func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error) {
  627. log.Error("TODO")
  628. return nil, errTODO
  629. }
  630. type transactionData struct {
  631. Name string
  632. Value interface{}
  633. }
  634. func newTransaction(name string, value interface{}) *types.Transaction {
  635. data, err := json.Marshal(transactionData{name, value})
  636. if err != nil {
  637. panic(err)
  638. }
  639. return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
  640. data)
  641. }
  642. // RollupForgeBatch is the interface to call the smart contract function
  643. func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (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. a := c.nextBlock().Auction
  652. ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
  653. if err != nil {
  654. return nil, err
  655. }
  656. if !ok {
  657. return nil, fmt.Errorf("incorrect slot")
  658. }
  659. // TODO: Verify proof
  660. // Auction
  661. err = a.forge(*c.addr)
  662. if err != nil {
  663. return nil, err
  664. }
  665. // TODO: If successful, store the tx in a successful array.
  666. // TODO: If failed, store the tx in a failed array.
  667. // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
  668. return c.addBatch(args)
  669. }
  670. // CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
  671. func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
  672. c.rw.Lock()
  673. defer c.rw.Unlock()
  674. if _, err := c.addBatch(args); err != nil {
  675. panic(err)
  676. }
  677. }
  678. func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
  679. nextBlock := c.nextBlock()
  680. r := nextBlock.Rollup
  681. r.State.StateRoot = args.NewStRoot
  682. if args.NewLastIdx < r.State.CurrentIdx {
  683. return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
  684. }
  685. r.State.CurrentIdx = args.NewLastIdx
  686. r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
  687. if args.L1Batch {
  688. r.State.CurrentToForgeL1TxsNum++
  689. if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
  690. r.State.LastToForgeL1TxsNum++
  691. r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
  692. }
  693. }
  694. ethTx := r.addTransaction(newTransaction("forgebatch", args))
  695. c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
  696. r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
  697. BatchNum: int64(len(r.State.ExitRoots)),
  698. EthTxHash: ethTx.Hash(),
  699. })
  700. return ethTx, nil
  701. }
  702. // RollupAddToken is the interface to call the smart contract function
  703. func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
  704. c.rw.Lock()
  705. defer c.rw.Unlock()
  706. cpy := c.nextBlock().copy()
  707. defer func() { c.revertIfErr(err, cpy) }()
  708. if c.addr == nil {
  709. return nil, eth.ErrAccountNil
  710. }
  711. nextBlock := c.nextBlock()
  712. r := nextBlock.Rollup
  713. if _, ok := r.State.TokenMap[tokenAddress]; ok {
  714. return nil, fmt.Errorf("Token %v already registered", tokenAddress)
  715. }
  716. if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
  717. return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken)
  718. }
  719. r.State.TokenMap[tokenAddress] = true
  720. r.State.TokenList = append(r.State.TokenList, tokenAddress)
  721. r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
  722. TokenID: uint32(len(r.State.TokenList) - 1)})
  723. return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
  724. }
  725. // RollupGetCurrentTokens is the interface to call the smart contract function
  726. func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
  727. c.rw.RLock()
  728. defer c.rw.RUnlock()
  729. log.Error("TODO")
  730. return nil, errTODO
  731. }
  732. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  733. func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
  734. c.rw.Lock()
  735. defer c.rw.Unlock()
  736. cpy := c.nextBlock().copy()
  737. defer func() { c.revertIfErr(err, cpy) }()
  738. if c.addr == nil {
  739. return nil, eth.ErrAccountNil
  740. }
  741. log.Error("TODO")
  742. return nil, errTODO
  743. }
  744. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  745. func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  746. c.rw.Lock()
  747. defer c.rw.Unlock()
  748. cpy := c.nextBlock().copy()
  749. defer func() { c.revertIfErr(err, cpy) }()
  750. if c.addr == nil {
  751. return nil, eth.ErrAccountNil
  752. }
  753. log.Error("TODO")
  754. return nil, errTODO
  755. }
  756. // RollupUpdateTokensHEZ is the interface to call the smart contract function
  757. // func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
  758. // c.rw.Lock()
  759. // defer c.rw.Unlock()
  760. // cpy := c.nextBlock().copy()
  761. // defer func() { c.revertIfErr(err, cpy) }()
  762. //
  763. // log.Error("TODO")
  764. // return nil, errTODO
  765. // }
  766. // RollupUpdateGovernance is the interface to call the smart contract function
  767. // func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
  768. // return nil, errTODO
  769. // }
  770. // RollupConstants returns the Constants of the Rollup Smart Contract
  771. func (c *Client) RollupConstants() (*eth.RollupPublicConstants, error) {
  772. c.rw.RLock()
  773. defer c.rw.RUnlock()
  774. log.Error("TODO")
  775. return nil, errTODO
  776. }
  777. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  778. func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
  779. c.rw.RLock()
  780. defer c.rw.RUnlock()
  781. block, ok := c.blocks[blockNum]
  782. if !ok {
  783. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  784. }
  785. return &block.Rollup.Events, &block.Eth.Hash, nil
  786. }
  787. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
  788. func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
  789. c.rw.RLock()
  790. defer c.rw.RUnlock()
  791. batch, ok := c.forgeBatchArgs[ethTxHash]
  792. if !ok {
  793. return nil, nil, fmt.Errorf("transaction not found")
  794. }
  795. return &batch.ForgeBatchArgs, &batch.Sender, nil
  796. }
  797. //
  798. // Auction
  799. //
  800. // AuctionSetSlotDeadline is the interface to call the smart contract function
  801. func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
  802. c.rw.Lock()
  803. defer c.rw.Unlock()
  804. cpy := c.nextBlock().copy()
  805. defer func() { c.revertIfErr(err, cpy) }()
  806. if c.addr == nil {
  807. return nil, eth.ErrAccountNil
  808. }
  809. log.Error("TODO")
  810. return nil, errTODO
  811. }
  812. // AuctionGetSlotDeadline is the interface to call the smart contract function
  813. func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
  814. c.rw.RLock()
  815. defer c.rw.RUnlock()
  816. log.Error("TODO")
  817. return 0, errTODO
  818. }
  819. // AuctionSetOpenAuctionSlots is the interface to call the smart contract function
  820. func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
  821. c.rw.Lock()
  822. defer c.rw.Unlock()
  823. cpy := c.nextBlock().copy()
  824. defer func() { c.revertIfErr(err, cpy) }()
  825. if c.addr == nil {
  826. return nil, eth.ErrAccountNil
  827. }
  828. log.Error("TODO")
  829. return nil, errTODO
  830. }
  831. // AuctionGetOpenAuctionSlots is the interface to call the smart contract function
  832. func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
  833. c.rw.RLock()
  834. defer c.rw.RUnlock()
  835. log.Error("TODO")
  836. return 0, errTODO
  837. }
  838. // AuctionSetClosedAuctionSlots is the interface to call the smart contract function
  839. func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
  840. c.rw.Lock()
  841. defer c.rw.Unlock()
  842. cpy := c.nextBlock().copy()
  843. defer func() { c.revertIfErr(err, cpy) }()
  844. if c.addr == nil {
  845. return nil, eth.ErrAccountNil
  846. }
  847. log.Error("TODO")
  848. return nil, errTODO
  849. }
  850. // AuctionGetClosedAuctionSlots is the interface to call the smart contract function
  851. func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
  852. c.rw.RLock()
  853. defer c.rw.RUnlock()
  854. log.Error("TODO")
  855. return 0, errTODO
  856. }
  857. // AuctionSetOutbidding is the interface to call the smart contract function
  858. func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
  859. c.rw.Lock()
  860. defer c.rw.Unlock()
  861. cpy := c.nextBlock().copy()
  862. defer func() { c.revertIfErr(err, cpy) }()
  863. if c.addr == nil {
  864. return nil, eth.ErrAccountNil
  865. }
  866. log.Error("TODO")
  867. return nil, errTODO
  868. }
  869. // AuctionGetOutbidding is the interface to call the smart contract function
  870. func (c *Client) AuctionGetOutbidding() (uint16, error) {
  871. c.rw.RLock()
  872. defer c.rw.RUnlock()
  873. log.Error("TODO")
  874. return 0, errTODO
  875. }
  876. // AuctionSetAllocationRatio is the interface to call the smart contract function
  877. func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
  878. c.rw.Lock()
  879. defer c.rw.Unlock()
  880. cpy := c.nextBlock().copy()
  881. defer func() { c.revertIfErr(err, cpy) }()
  882. if c.addr == nil {
  883. return nil, eth.ErrAccountNil
  884. }
  885. log.Error("TODO")
  886. return nil, errTODO
  887. }
  888. // AuctionGetAllocationRatio is the interface to call the smart contract function
  889. func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
  890. c.rw.RLock()
  891. defer c.rw.RUnlock()
  892. log.Error("TODO")
  893. return [3]uint16{}, errTODO
  894. }
  895. // AuctionSetDonationAddress is the interface to call the smart contract function
  896. func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
  897. c.rw.Lock()
  898. defer c.rw.Unlock()
  899. cpy := c.nextBlock().copy()
  900. defer func() { c.revertIfErr(err, cpy) }()
  901. if c.addr == nil {
  902. return nil, eth.ErrAccountNil
  903. }
  904. log.Error("TODO")
  905. return nil, errTODO
  906. }
  907. // AuctionGetDonationAddress is the interface to call the smart contract function
  908. func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
  909. c.rw.RLock()
  910. defer c.rw.RUnlock()
  911. log.Error("TODO")
  912. return nil, errTODO
  913. }
  914. // AuctionSetBootCoordinator is the interface to call the smart contract function
  915. func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
  916. c.rw.Lock()
  917. defer c.rw.Unlock()
  918. cpy := c.nextBlock().copy()
  919. defer func() { c.revertIfErr(err, cpy) }()
  920. if c.addr == nil {
  921. return nil, eth.ErrAccountNil
  922. }
  923. log.Error("TODO")
  924. return nil, errTODO
  925. }
  926. // AuctionGetBootCoordinator is the interface to call the smart contract function
  927. func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
  928. c.rw.RLock()
  929. defer c.rw.RUnlock()
  930. currentBlock := c.currentBlock()
  931. a := currentBlock.Auction
  932. return &a.Vars.BootCoordinator, nil
  933. }
  934. // AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
  935. func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
  936. c.rw.Lock()
  937. defer c.rw.Unlock()
  938. cpy := c.nextBlock().copy()
  939. defer func() { c.revertIfErr(err, cpy) }()
  940. if c.addr == nil {
  941. return nil, eth.ErrAccountNil
  942. }
  943. log.Error("TODO")
  944. return nil, errTODO
  945. }
  946. // AuctionSetCoordinator is the interface to call the smart contract function
  947. func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
  948. c.rw.Lock()
  949. defer c.rw.Unlock()
  950. cpy := c.nextBlock().copy()
  951. defer func() { c.revertIfErr(err, cpy) }()
  952. if c.addr == nil {
  953. return nil, eth.ErrAccountNil
  954. }
  955. nextBlock := c.nextBlock()
  956. a := nextBlock.Auction
  957. a.State.Coordinators[*c.addr] = &eth.Coordinator{
  958. Forger: forger,
  959. URL: URL,
  960. }
  961. a.Events.SetCoordinator = append(a.Events.SetCoordinator,
  962. eth.AuctionEventSetCoordinator{
  963. BidderAddress: *c.addr,
  964. ForgerAddress: forger,
  965. CoordinatorURL: URL,
  966. })
  967. type data struct {
  968. BidderAddress ethCommon.Address
  969. ForgerAddress ethCommon.Address
  970. URL string
  971. }
  972. return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
  973. }
  974. // AuctionIsRegisteredCoordinator is the interface to call the smart contract function
  975. func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
  976. c.rw.RLock()
  977. defer c.rw.RUnlock()
  978. log.Error("TODO")
  979. return false, errTODO
  980. }
  981. // AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
  982. func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
  983. c.rw.Lock()
  984. defer c.rw.Unlock()
  985. cpy := c.nextBlock().copy()
  986. defer func() { c.revertIfErr(err, cpy) }()
  987. if c.addr == nil {
  988. return nil, eth.ErrAccountNil
  989. }
  990. log.Error("TODO")
  991. return nil, errTODO
  992. }
  993. // AuctionGetSlotNumber is the interface to call the smart contract function
  994. func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
  995. c.rw.RLock()
  996. defer c.rw.RUnlock()
  997. currentBlock := c.currentBlock()
  998. a := currentBlock.Auction
  999. return a.getSlotNumber(blockNum), nil
  1000. }
  1001. // AuctionGetCurrentSlotNumber is the interface to call the smart contract function
  1002. func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
  1003. c.rw.RLock()
  1004. defer c.rw.RUnlock()
  1005. log.Error("TODO")
  1006. return 0, errTODO
  1007. }
  1008. // AuctionGetMinBidBySlot is the interface to call the smart contract function
  1009. func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
  1010. c.rw.RLock()
  1011. defer c.rw.RUnlock()
  1012. log.Error("TODO")
  1013. return nil, errTODO
  1014. }
  1015. // AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
  1016. func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
  1017. c.rw.RLock()
  1018. defer c.rw.RUnlock()
  1019. log.Error("TODO")
  1020. return nil, errTODO
  1021. }
  1022. // AuctionGetSlotSet is the interface to call the smart contract function
  1023. func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
  1024. c.rw.RLock()
  1025. defer c.rw.RUnlock()
  1026. log.Error("TODO")
  1027. return nil, errTODO
  1028. }
  1029. // AuctionTokensReceived is the interface to call the smart contract function
  1030. // func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
  1031. // return errTODO
  1032. // }
  1033. // AuctionBid is the interface to call the smart contract function
  1034. func (c *Client) AuctionBid(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
  1035. c.rw.Lock()
  1036. defer c.rw.Unlock()
  1037. cpy := c.nextBlock().copy()
  1038. defer func() { func() { c.revertIfErr(err, cpy) }() }()
  1039. if c.addr == nil {
  1040. return nil, eth.ErrAccountNil
  1041. }
  1042. nextBlock := c.nextBlock()
  1043. a := nextBlock.Auction
  1044. if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  1045. return nil, errBidClosed
  1046. }
  1047. if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
  1048. return nil, errBidNotOpen
  1049. }
  1050. minBid, err := a.getMinBidBySlot(slot)
  1051. if err != nil {
  1052. return nil, err
  1053. }
  1054. if bidAmount.Cmp(minBid) == -1 {
  1055. return nil, errBidBelowMin
  1056. }
  1057. if _, ok := a.State.Coordinators[*c.addr]; !ok {
  1058. return nil, errCoordNotReg
  1059. }
  1060. slotState, ok := a.State.Slots[slot]
  1061. if !ok {
  1062. slotState = eth.NewSlotState()
  1063. a.State.Slots[slot] = slotState
  1064. }
  1065. slotState.Bidder = *c.addr
  1066. slotState.BidAmount = bidAmount
  1067. a.Events.NewBid = append(a.Events.NewBid,
  1068. eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
  1069. type data struct {
  1070. Slot int64
  1071. BidAmount *big.Int
  1072. Bidder ethCommon.Address
  1073. }
  1074. return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
  1075. }
  1076. // AuctionMultiBid is the interface to call the smart contract function
  1077. func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (tx *types.Transaction, err error) {
  1078. c.rw.Lock()
  1079. defer c.rw.Unlock()
  1080. cpy := c.nextBlock().copy()
  1081. defer func() { c.revertIfErr(err, cpy) }()
  1082. if c.addr == nil {
  1083. return nil, eth.ErrAccountNil
  1084. }
  1085. log.Error("TODO")
  1086. return nil, errTODO
  1087. }
  1088. // AuctionCanForge is the interface to call the smart contract function
  1089. func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
  1090. c.rw.RLock()
  1091. defer c.rw.RUnlock()
  1092. currentBlock := c.currentBlock()
  1093. a := currentBlock.Auction
  1094. return a.canForge(forger, blockNum)
  1095. }
  1096. // AuctionForge is the interface to call the smart contract function
  1097. func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
  1098. c.rw.Lock()
  1099. defer c.rw.Unlock()
  1100. cpy := c.nextBlock().copy()
  1101. defer func() { c.revertIfErr(err, cpy) }()
  1102. if c.addr == nil {
  1103. return nil, eth.ErrAccountNil
  1104. }
  1105. log.Error("TODO")
  1106. return nil, errTODO
  1107. }
  1108. // AuctionClaimHEZ is the interface to call the smart contract function
  1109. func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
  1110. c.rw.Lock()
  1111. defer c.rw.Unlock()
  1112. cpy := c.nextBlock().copy()
  1113. defer func() { c.revertIfErr(err, cpy) }()
  1114. if c.addr == nil {
  1115. return nil, eth.ErrAccountNil
  1116. }
  1117. log.Error("TODO")
  1118. return nil, errTODO
  1119. }
  1120. // AuctionGetClaimableHEZ is the interface to call the smart contract function
  1121. func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
  1122. c.rw.RLock()
  1123. defer c.rw.RUnlock()
  1124. log.Error("TODO")
  1125. return nil, errTODO
  1126. }
  1127. // AuctionConstants returns the Constants of the Auction Smart Contract
  1128. func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
  1129. c.rw.RLock()
  1130. defer c.rw.RUnlock()
  1131. return c.auctionConstants, nil
  1132. }
  1133. // AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
  1134. func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
  1135. c.rw.RLock()
  1136. defer c.rw.RUnlock()
  1137. block, ok := c.blocks[blockNum]
  1138. if !ok {
  1139. return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
  1140. }
  1141. return &block.Auction.Events, &block.Eth.Hash, nil
  1142. }