Add e2e tests two tokens support
This commit is contained in:
parent
1360c79e69
commit
406ede9352
@ -13,6 +13,7 @@ const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/Rewardab
|
|||||||
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
|
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
|
||||||
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
|
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
|
||||||
const BOX_ABI = require('../contracts/build/contracts/Box').abi
|
const BOX_ABI = require('../contracts/build/contracts/Box').abi
|
||||||
|
const SAI_TOP = require('../contracts/build/contracts/SaiTopMock').abi
|
||||||
|
|
||||||
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
|
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
|
||||||
const { BRIDGE_MODES } = require('./constants')
|
const { BRIDGE_MODES } = require('./constants')
|
||||||
@ -92,5 +93,6 @@ module.exports = {
|
|||||||
ERC20_BYTES32_ABI,
|
ERC20_BYTES32_ABI,
|
||||||
HOME_AMB_ABI,
|
HOME_AMB_ABI,
|
||||||
FOREIGN_AMB_ABI,
|
FOREIGN_AMB_ABI,
|
||||||
BOX_ABI
|
BOX_ABI,
|
||||||
|
SAI_TOP
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,6 @@
|
|||||||
"address": "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b",
|
"address": "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b",
|
||||||
"privateKey": "0x8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
"privateKey": "0x8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||||
},
|
},
|
||||||
"owner": {
|
|
||||||
"address": "0x379a38a225fadb4a3769391ab26e2440681bf098",
|
|
||||||
"privateKey": "0x19fba401d77e4113b15095e9aa7117bcd25adcfac7f6111f8298894eef443600"
|
|
||||||
},
|
|
||||||
"blockGenerator": {
|
"blockGenerator": {
|
||||||
"address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7",
|
"address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7",
|
||||||
"privateKey": "0xd6143d390d8b28c33601bb0fe29392fb1c35c24ccfe8722c09c2bdd6ada2699f"
|
"privateKey": "0xd6143d390d8b28c33601bb0fe29392fb1c35c24ccfe8722c09c2bdd6ada2699f"
|
||||||
@ -38,6 +34,7 @@
|
|||||||
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||||
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||||
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
||||||
|
"saiTop": "0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3",
|
||||||
"ui": "http://localhost:3002",
|
"ui": "http://localhost:3002",
|
||||||
"monitor": "http://monitor-erc20-native:3012"
|
"monitor": "http://monitor-erc20-native:3012"
|
||||||
},
|
},
|
||||||
|
@ -22,6 +22,8 @@ while [ "$1" != "" ]; do
|
|||||||
docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures
|
docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures
|
||||||
docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request
|
docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request
|
||||||
docker-compose run -d oracle-erc20-native yarn watcher:transfer
|
docker-compose run -d oracle-erc20-native yarn watcher:transfer
|
||||||
|
docker-compose run -d oracle-erc20-native yarn watcher:half-duplex-transfer
|
||||||
|
docker-compose run -d oracle-erc20-native yarn worker:swap-tokens
|
||||||
docker-compose run -d oracle-amb yarn watcher:signature-request
|
docker-compose run -d oracle-amb yarn watcher:signature-request
|
||||||
docker-compose run -d oracle-amb yarn watcher:collected-signatures
|
docker-compose run -d oracle-amb yarn watcher:collected-signatures
|
||||||
docker-compose run -d oracle-amb yarn watcher:affirmation-request
|
docker-compose run -d oracle-amb yarn watcher:affirmation-request
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const promiseRetry = require('promise-retry')
|
const promiseRetry = require('promise-retry')
|
||||||
const { user, secondUser, ercToNativeBridge, homeRPC, foreignRPC } = require('../../e2e-commons/constants.json')
|
const {
|
||||||
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../../commons')
|
user,
|
||||||
|
secondUser,
|
||||||
|
validator,
|
||||||
|
ercToNativeBridge,
|
||||||
|
homeRPC,
|
||||||
|
foreignRPC
|
||||||
|
} = require('../../e2e-commons/constants.json')
|
||||||
|
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI, SAI_TOP } = require('../../commons')
|
||||||
const { generateNewBlock } = require('../../e2e-commons/utils')
|
const { generateNewBlock } = require('../../e2e-commons/utils')
|
||||||
|
|
||||||
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
|
||||||
@ -15,11 +22,24 @@ const { toBN } = foreignWeb3.utils
|
|||||||
|
|
||||||
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
homeWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||||
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||||
|
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||||
|
|
||||||
const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToNativeBridge.foreignToken)
|
const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToNativeBridge.foreignToken)
|
||||||
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
|
||||||
describe('erc to native', () => {
|
describe('erc to native', () => {
|
||||||
|
let halfDuplexTokenAddress
|
||||||
|
let halfDuplexToken
|
||||||
|
before(async () => {
|
||||||
|
halfDuplexTokenAddress = await foreignBridge.methods.halfDuplexErc20token().call()
|
||||||
|
halfDuplexToken = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, halfDuplexTokenAddress)
|
||||||
|
|
||||||
|
// set min threshold for swap
|
||||||
|
await foreignBridge.methods.setMinHDTokenBalance(foreignWeb3.utils.toWei('1', 'ether')).send({
|
||||||
|
from: validator.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
})
|
||||||
it('should convert tokens in foreign to coins in home', async () => {
|
it('should convert tokens in foreign to coins in home', async () => {
|
||||||
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
const balance = await erc20Token.methods.balanceOf(user.address).call()
|
||||||
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
@ -92,6 +112,237 @@ describe('erc to native', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
it('should convert half duplex token in foreign to native token in home', async () => {
|
||||||
|
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const bridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
const bridgeHalfDuplexBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
assert(toBN(bridgeHalfDuplexBalance).isZero(), 'Bridge balance should be zero')
|
||||||
|
|
||||||
|
const valueToTransfer = foreignWeb3.utils.toWei('1', 'ether')
|
||||||
|
|
||||||
|
// this transfer won't trigger a call to swap tokens
|
||||||
|
await halfDuplexToken.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Send a trivial transaction to generate a new block since the watcher
|
||||||
|
// is configured to wait 1 confirmation block
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
// check that balance increases
|
||||||
|
await promiseRetry(async retry => {
|
||||||
|
const balance = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
if (toBN(balance).lte(toBN(originalBalanceOnHome))) {
|
||||||
|
retry()
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
toBN(balance).eq(toBN(originalBalanceOnHome).add(toBN(valueToTransfer))),
|
||||||
|
'User balance should be increased by the half duplex token transfer'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const updatedBridgeHalfDuplexBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
assert(
|
||||||
|
toBN(updatedBridgeHalfDuplexBalance).eq(toBN(bridgeHalfDuplexBalance).add(toBN(valueToTransfer))),
|
||||||
|
'Bridge balance should reflect the transfer value'
|
||||||
|
)
|
||||||
|
|
||||||
|
// this transfer will trigger call to swap tokens
|
||||||
|
await halfDuplexToken.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
await promiseRetry(async retry => {
|
||||||
|
const userBalance = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
|
||||||
|
if (
|
||||||
|
toBN(userBalance).lte(toBN(updatedBalanceOnHome)) ||
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).lte(toBN(bridgeErc20TokenBalance))
|
||||||
|
) {
|
||||||
|
retry()
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
toBN(userBalance).eq(toBN(updatedBalanceOnHome).add(toBN(valueToTransfer))),
|
||||||
|
'User balance should be increased by the half duplex token transfer'
|
||||||
|
)
|
||||||
|
const updatedBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
assert(toBN(updatedBalance).isZero(), 'Half duplex bridge balance should be zero')
|
||||||
|
assert(
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).eq(
|
||||||
|
toBN(bridgeErc20TokenBalance).add(toBN(foreignWeb3.utils.toWei('2', 'ether')))
|
||||||
|
),
|
||||||
|
'Erc20 token balance should be correctly increased by the token swap'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('should convert half duplex token in foreign to native token in home for alternative receiver ', async () => {
|
||||||
|
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const initialBalanceSecondUser = await homeWeb3.eth.getBalance(secondUser.address)
|
||||||
|
const bridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
|
||||||
|
const valueToTransfer = foreignWeb3.utils.toWei('1', 'ether')
|
||||||
|
|
||||||
|
// approve tokens to foreign bridge
|
||||||
|
await halfDuplexToken.methods
|
||||||
|
.approve(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer)
|
||||||
|
.send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
// call bridge method to transfer tokens to a different recipient
|
||||||
|
await foreignBridge.methods['relayTokens(address,uint256,address)'](
|
||||||
|
secondUser.address,
|
||||||
|
valueToTransfer,
|
||||||
|
halfDuplexTokenAddress
|
||||||
|
)
|
||||||
|
.send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Send a trivial transaction to generate a new block since the watcher
|
||||||
|
// is configured to wait 1 confirmation block
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
// check that balance increases
|
||||||
|
await promiseRetry(async retry => {
|
||||||
|
const secondUserbalance = await homeWeb3.eth.getBalance(secondUser.address)
|
||||||
|
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
const userbalance = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
assert(toBN(userbalance).lte(toBN(originalBalanceOnHome)), 'User balance should be the same')
|
||||||
|
if (
|
||||||
|
toBN(secondUserbalance).lte(toBN(initialBalanceSecondUser)) ||
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).lte(toBN(bridgeErc20TokenBalance))
|
||||||
|
) {
|
||||||
|
retry()
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
toBN(secondUserbalance).eq(toBN(initialBalanceSecondUser).add(toBN(valueToTransfer))),
|
||||||
|
'User balance should be increased by the half duplex token transfer'
|
||||||
|
)
|
||||||
|
const updatedHDBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
assert(toBN(updatedHDBalance).isZero(), 'Half duplex bridge balance should be zero')
|
||||||
|
assert(
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).eq(toBN(bridgeErc20TokenBalance).add(toBN(valueToTransfer))),
|
||||||
|
'Erc20 token balance should be correctly increased by the token swap'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('should not relay half duplex token transfer after Emergency Shutdown', async () => {
|
||||||
|
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const bridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
const bridgeHalfDuplexBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
|
||||||
|
const block = await foreignWeb3.eth.getBlock('latest')
|
||||||
|
const saiTop = new foreignWeb3.eth.Contract(SAI_TOP, ercToNativeBridge.saiTop)
|
||||||
|
|
||||||
|
// Trigger Emergency Shutdown
|
||||||
|
await saiTop.methods
|
||||||
|
.setCaged(block.timestamp)
|
||||||
|
.send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
const valueToTransfer = foreignWeb3.utils.toWei('1', 'ether')
|
||||||
|
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
// this transfer won't trigger a call to swap tokens
|
||||||
|
await halfDuplexToken.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Send a trivial transaction to generate a new block since the watcher
|
||||||
|
// is configured to wait 1 confirmation block
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
// check that transfer and swap are not processed in the next blocks.
|
||||||
|
await promiseRetry(async (retry, number) => {
|
||||||
|
const balanceOnHome = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const currentBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
const currentBridgeHalfDuplexBalance = await halfDuplexToken.methods
|
||||||
|
.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
.call()
|
||||||
|
|
||||||
|
assert(toBN(balanceOnHome).eq(toBN(originalBalanceOnHome)), 'User balance should be the same')
|
||||||
|
assert(
|
||||||
|
toBN(currentBridgeHalfDuplexBalance).eq(toBN(bridgeHalfDuplexBalance).add(toBN(valueToTransfer))),
|
||||||
|
'Half duplex balance should be the value of transfer'
|
||||||
|
)
|
||||||
|
assert(toBN(currentBridgeErc20TokenBalance).eq(toBN(bridgeErc20TokenBalance)), 'erc20 balance should not change')
|
||||||
|
|
||||||
|
// generate new blocks
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
// after several retries, the state is corrects
|
||||||
|
if (number < 4) {
|
||||||
|
retry()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// let's undo the Emergency Shutdown to check that the oracle is still working
|
||||||
|
await saiTop.methods.setCaged('0').send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
|
||||||
|
const newValueToTransfer = foreignWeb3.utils.toWei('2', 'ether')
|
||||||
|
|
||||||
|
await halfDuplexToken.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, newValueToTransfer).send({
|
||||||
|
from: user.address,
|
||||||
|
gas: '1000000'
|
||||||
|
})
|
||||||
|
|
||||||
|
await generateNewBlock(foreignWeb3, user.address)
|
||||||
|
|
||||||
|
await promiseRetry(async retry => {
|
||||||
|
const userBalance = await homeWeb3.eth.getBalance(user.address)
|
||||||
|
const updatedBridgeErc20TokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
|
||||||
|
if (
|
||||||
|
toBN(userBalance).lte(toBN(originalBalanceOnHome)) ||
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).lte(toBN(bridgeErc20TokenBalance))
|
||||||
|
) {
|
||||||
|
retry()
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
toBN(userBalance).eq(toBN(originalBalanceOnHome).add(toBN(newValueToTransfer))),
|
||||||
|
'User balance should be increased by the half duplex token transfer'
|
||||||
|
)
|
||||||
|
const updatedHDBalance = await halfDuplexToken.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call()
|
||||||
|
assert(toBN(updatedHDBalance).isZero(), 'Half duplex bridge balance should be zero')
|
||||||
|
assert(
|
||||||
|
toBN(updatedBridgeErc20TokenBalance).eq(
|
||||||
|
toBN(bridgeErc20TokenBalance)
|
||||||
|
.add(toBN(valueToTransfer))
|
||||||
|
.add(toBN(newValueToTransfer))
|
||||||
|
),
|
||||||
|
'Erc20 token balance should be correctly increased by the token swap'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
it('should convert coins in home to tokens in foreign', async () => {
|
it('should convert coins in home to tokens in foreign', async () => {
|
||||||
const originalBalance = await erc20Token.methods.balanceOf(user.address).call()
|
const originalBalance = await erc20Token.methods.balanceOf(user.address).call()
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@
|
|||||||
"0x1": "0x4441490000000000000000000000000000000000000000000000000000000006",
|
"0x1": "0x4441490000000000000000000000000000000000000000000000000000000006",
|
||||||
"0x2": "0x12",
|
"0x2": "0x12",
|
||||||
"0x4": "0x00000000000000000000000000000000000000000000001043561a8829300000",
|
"0x4": "0x00000000000000000000000000000000000000000000001043561a8829300000",
|
||||||
"0x6": "0x379a38a225fadb4a3769391ab26e2440681bf098",
|
"0x6": "0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849",
|
||||||
"0xe72abea4d7a02a1dd3bab9806f38066f472bc02778742ed50ed69de48da9c3e6" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000",
|
"0xe72abea4d7a02a1dd3bab9806f38066f472bc02778742ed50ed69de48da9c3e6" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000",
|
||||||
"0xc19ddbb1e237d15aa362708548b7cbc089c94e4977af9e54c2f09f0ae28a35fc" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000",
|
"0xc19ddbb1e237d15aa362708548b7cbc089c94e4977af9e54c2f09f0ae28a35fc" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000",
|
||||||
"0xca2b12ce800b15ade60b8e814bbbf66b91734af718ac5562e6b8adc9b4e5b629" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000"
|
"0xca2b12ce800b15ade60b8e814bbbf66b91734af718ac5562e6b8adc9b4e5b629" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000"
|
||||||
|
Loading…
Reference in New Issue
Block a user