Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch deposit helper script #11

Merged
merged 3 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.env
.git/
.idea/
build/
coverage/
node_modules/
coverage.json
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"@openzeppelin/contracts": "^4.3.2",
"@truffle/hdwallet-provider": "^1.4.2",
"dotenv": "^10.0.0",
"truffle": "^5.4.3"
"truffle": "^5.4.3",
"web3": "^1.6.0"
},
"devDependencies": {
"chai": "^4.3.4",
Expand Down
16 changes: 16 additions & 0 deletions scripts/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
STAKING_ACCOUNT_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000000

RPC_URL=https://dai.poa.network
GAS_PRICE=1000000000

# number of deposits in one transaction, should be in range [1, 128]
BATCH_SIZE=128
# total number of deposits to read from file
N=256
# index of the first deposit to read from file
OFFSET=0

# address of the wrapped SBC token
TOKEN_ADDRESS=0x0000000000000000000000000000000000000000
# address of the SBC deposit contract
DEPOSIT_CONTRACT_ADDRESS=0x0000000000000000000000000000000000000000
13 changes: 13 additions & 0 deletions scripts/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM node:14-alpine

WORKDIR /app

COPY package.json yarn.lock ./

RUN yarn install

COPY . .

RUN yarn compile

ENTRYPOINT ["node", "./scripts/deposit.js"]
16 changes: 16 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Batch deposit helper script

Use this script to send multiple SBC deposits in batches.

First, make sure you have generated valid deposits via a deposit cli (https://github.com/openethereum/sbc-deposit-cli).
You will need a `deposit_data.json` file from there.

Now, copy `./scripts/.env.example` file to `./scripts/.env` and update necessary parameters.

Then run the following:
```bash
docker build -f ./scripts/Dockerfile -t batch_deposit .
docker run --env-file ./scripts/.env -v /path/to/deposit_data.json:/tmp/deposit_data.json batch_deposit /tmp/deposit_data.json
```

This will read the `deposit_data.json` file and submit deposits from `OFFSET` to `OFFSET + N - 1` to the deposit contract.
80 changes: 80 additions & 0 deletions scripts/deposit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const Web3 = require('web3')

const { abi } = require('../build/contracts/IERC677.json')

const { RPC_URL, GAS_PRICE, STAKING_ACCOUNT_PRIVATE_KEY, BATCH_SIZE, N, OFFSET, TOKEN_ADDRESS, DEPOSIT_CONTRACT_ADDRESS } = process.env

const web3 = new Web3(RPC_URL)
const { address } = web3.eth.accounts.wallet.add(STAKING_ACCOUNT_PRIVATE_KEY)

const depositData = require(process.argv[2])

const batchSize = parseInt(BATCH_SIZE, 10)
const offset = parseInt(OFFSET, 10)
const n = parseInt(N, 10)
async function main() {
const token = new web3.eth.Contract(abi, TOKEN_ADDRESS)
const deposits = depositData.slice(offset, offset + n)

const wc = deposits[0].withdrawal_credentials
if (!deposits.every(d => d.withdrawal_credentials === wc)) {
console.log('Withdrawal credentials do not match')
return
}

if (!deposits.every(d => d.amount === 32000000000)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to check that the staking account owns the corresponding amount of tokens?

console.log('Amount should be exactly 32 tokens for batch deposits')
return
}

const depositAmountBN = web3.utils.toBN(32).mul(web3.utils.toBN('1000000000000000000'))
const tokenBalance = await token.methods.balanceOf(address).call()

if (web3.utils.toBN(tokenBalance).lt(depositAmountBN)) {
console.log(`Token balance is not enough to cover all deposits, have ${tokenBalance}, required ${depositAmountBN.toString()}`)
return
}

console.log(`Sending ${Math.ceil(deposits.length / batchSize)} deposit transactions for ${deposits.length} deposits in batches of ${batchSize} deposits`)
let balance = await web3.eth.getBalance(address).then(web3.utils.toBN)
let nonce = await web3.eth.getTransactionCount(address)
let count = 0
let data = '0x' + wc
for (let i = 0; i < deposits.length; i++) {
const deposit = deposits[i]
data += deposit.pubkey
data += deposit.signature
data += deposit.deposit_data_root
count++

if (count === batchSize || i === deposits.length - 1) {
const amount = depositAmountBN.muln(count)
const call = token.methods.transferAndCall(DEPOSIT_CONTRACT_ADDRESS, amount, data)
let gas
try {
gas = await call.estimateGas({ from: address })
} catch (e) {
console.log('Gas estimation failed:', e.message)
return
}
const gasLimit = Math.ceil(gas * 1.5)
const feeBN = web3.utils.toBN(GAS_PRICE).muln(gasLimit)
if (balance.lt(feeBN)) {
console.log(`Native balance is not enough to cover tx fee, have ${balance.toString()}, required ${feeBN.toString()}`)
return
}
const receipt = await call.send({
from: address,
nonce: nonce++,
gas: gasLimit,
gasPrice: GAS_PRICE,
})
balance = balance.sub(web3.utils.toBN(GAS_PRICE).muln(receipt.gasUsed))
console.log(`\t${count} next deposits: ${receipt.transactionHash}`)
data = '0x' + wc
count = 0
}
}
}

main()
Loading