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.

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