|
|
|
|
@@ -3,7 +3,7 @@ import { solidity, MockProvider, deployContract } from 'ethereum-waffle'
|
|
|
|
|
import { Contract, BigNumber, constants } from 'ethers'
|
|
|
|
|
import BalanceTree from '../src/balance-tree'
|
|
|
|
|
|
|
|
|
|
import Airdrop from '../build/AirdropTokenDistributor.json'
|
|
|
|
|
import Distributor from '../build/MerkleDistributor.json'
|
|
|
|
|
import TestERC20 from '../build/TestERC20.json'
|
|
|
|
|
import { parseBalanceMap } from '../src/parse-balance-map'
|
|
|
|
|
|
|
|
|
|
@@ -15,7 +15,7 @@ const overrides = {
|
|
|
|
|
|
|
|
|
|
const ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
|
|
|
|
|
|
|
|
describe('AirdropTokenDistributor', () => {
|
|
|
|
|
describe('MerkleDistributor', () => {
|
|
|
|
|
const provider = new MockProvider({
|
|
|
|
|
ganacheOptions: {
|
|
|
|
|
hardfork: 'istanbul',
|
|
|
|
|
@@ -34,129 +34,153 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
|
|
|
|
|
describe('#token', () => {
|
|
|
|
|
it('returns the token address', async () => {
|
|
|
|
|
const airdrop = await deployContract(wallet0, Airdrop, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
expect(await airdrop.token()).to.eq(token.address)
|
|
|
|
|
const distributor = await deployContract(wallet0, Distributor, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
expect(await distributor.token()).to.eq(token.address)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('#merkleRoot', () => {
|
|
|
|
|
it('returns the zero merkle root', async () => {
|
|
|
|
|
const airdrop = await deployContract(wallet0, Airdrop, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
expect(await airdrop.merkleRoot()).to.eq(ZERO_BYTES32)
|
|
|
|
|
const distributor = await deployContract(wallet0, Distributor, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
expect(await distributor.merkleRoot()).to.eq(ZERO_BYTES32)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('#claim', () => {
|
|
|
|
|
it('fails for empty proof', async () => {
|
|
|
|
|
const airdrop = await deployContract(wallet0, Airdrop, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 10, [])).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Invalid proof.'
|
|
|
|
|
const distributor = await deployContract(wallet0, Distributor, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 10, [])).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Invalid proof.'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('fails for invalid index', async () => {
|
|
|
|
|
const airdrop = await deployContract(wallet0, Airdrop, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 10, [])).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Invalid proof.'
|
|
|
|
|
const distributor = await deployContract(wallet0, Distributor, [token.address, ZERO_BYTES32], overrides)
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 10, [])).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Invalid proof.'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('two account tree', () => {
|
|
|
|
|
let airdrop: Contract
|
|
|
|
|
let distributor: Contract
|
|
|
|
|
let tree: BalanceTree
|
|
|
|
|
beforeEach('deploy', async () => {
|
|
|
|
|
tree = new BalanceTree([
|
|
|
|
|
{ account: wallet0.address, amount: BigNumber.from(100) },
|
|
|
|
|
{ account: wallet1.address, amount: BigNumber.from(101) },
|
|
|
|
|
])
|
|
|
|
|
airdrop = await deployContract(wallet0, Airdrop, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(airdrop.address, 201)
|
|
|
|
|
distributor = await deployContract(wallet0, Distributor, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(distributor.address, 201)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('successful claim', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 100, proof0, overrides))
|
|
|
|
|
.to.emit(airdrop, 'Claimed')
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 100, proof0, overrides))
|
|
|
|
|
.to.emit(distributor, 'Claimed')
|
|
|
|
|
.withArgs(0, wallet0.address, 100)
|
|
|
|
|
const proof1 = tree.getProof(1, wallet1.address, BigNumber.from(101))
|
|
|
|
|
await expect(airdrop.claim(1, wallet1.address, 101, proof1, overrides))
|
|
|
|
|
.to.emit(airdrop, 'Claimed')
|
|
|
|
|
await expect(distributor.claim(1, wallet1.address, 101, proof1, overrides))
|
|
|
|
|
.to.emit(distributor, 'Claimed')
|
|
|
|
|
.withArgs(1, wallet1.address, 101)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('transfers the token', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
expect(await token.balanceOf(wallet0.address)).to.eq(0)
|
|
|
|
|
await airdrop.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
await distributor.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
expect(await token.balanceOf(wallet0.address)).to.eq(100)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('must have enough to transfer', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await token.setBalance(airdrop.address, 99)
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 100, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
await token.setBalance(distributor.address, 99)
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 100, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'ERC20: transfer amount exceeds balance'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('sets #isClaimed', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
expect(await airdrop.isClaimed(0)).to.eq(false)
|
|
|
|
|
expect(await airdrop.isClaimed(1)).to.eq(false)
|
|
|
|
|
await airdrop.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
expect(await airdrop.isClaimed(0)).to.eq(true)
|
|
|
|
|
expect(await airdrop.isClaimed(1)).to.eq(false)
|
|
|
|
|
expect(await distributor.isClaimed(0)).to.eq(false)
|
|
|
|
|
expect(await distributor.isClaimed(1)).to.eq(false)
|
|
|
|
|
await distributor.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
expect(await distributor.isClaimed(0)).to.eq(true)
|
|
|
|
|
expect(await distributor.isClaimed(1)).to.eq(false)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('cannot allow two claims', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await airdrop.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 100, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Drop already claimed.'
|
|
|
|
|
await distributor.claim(0, wallet0.address, 100, proof0, overrides)
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 100, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Drop already claimed.'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('cannot claim more than once: 0 and then 1', async () => {
|
|
|
|
|
await airdrop.claim(0, wallet0.address, 100, tree.getProof(0, wallet0.address, BigNumber.from(100)), overrides)
|
|
|
|
|
await airdrop.claim(1, wallet1.address, 101, tree.getProof(1, wallet1.address, BigNumber.from(101)), overrides)
|
|
|
|
|
await distributor.claim(
|
|
|
|
|
0,
|
|
|
|
|
wallet0.address,
|
|
|
|
|
100,
|
|
|
|
|
tree.getProof(0, wallet0.address, BigNumber.from(100)),
|
|
|
|
|
overrides
|
|
|
|
|
)
|
|
|
|
|
await distributor.claim(
|
|
|
|
|
1,
|
|
|
|
|
wallet1.address,
|
|
|
|
|
101,
|
|
|
|
|
tree.getProof(1, wallet1.address, BigNumber.from(101)),
|
|
|
|
|
overrides
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
|
airdrop.claim(0, wallet0.address, 100, tree.getProof(0, wallet0.address, BigNumber.from(100)), overrides)
|
|
|
|
|
).to.be.revertedWith('AirdropTokenDistributor: Drop already claimed.')
|
|
|
|
|
distributor.claim(0, wallet0.address, 100, tree.getProof(0, wallet0.address, BigNumber.from(100)), overrides)
|
|
|
|
|
).to.be.revertedWith('MerkleDistributor: Drop already claimed.')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('cannot claim more than once: 1 and then 0', async () => {
|
|
|
|
|
await airdrop.claim(1, wallet1.address, 101, tree.getProof(1, wallet1.address, BigNumber.from(101)), overrides)
|
|
|
|
|
await airdrop.claim(0, wallet0.address, 100, tree.getProof(0, wallet0.address, BigNumber.from(100)), overrides)
|
|
|
|
|
await distributor.claim(
|
|
|
|
|
1,
|
|
|
|
|
wallet1.address,
|
|
|
|
|
101,
|
|
|
|
|
tree.getProof(1, wallet1.address, BigNumber.from(101)),
|
|
|
|
|
overrides
|
|
|
|
|
)
|
|
|
|
|
await distributor.claim(
|
|
|
|
|
0,
|
|
|
|
|
wallet0.address,
|
|
|
|
|
100,
|
|
|
|
|
tree.getProof(0, wallet0.address, BigNumber.from(100)),
|
|
|
|
|
overrides
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
|
airdrop.claim(1, wallet1.address, 101, tree.getProof(1, wallet1.address, BigNumber.from(101)), overrides)
|
|
|
|
|
).to.be.revertedWith('AirdropTokenDistributor: Drop already claimed.')
|
|
|
|
|
distributor.claim(1, wallet1.address, 101, tree.getProof(1, wallet1.address, BigNumber.from(101)), overrides)
|
|
|
|
|
).to.be.revertedWith('MerkleDistributor: Drop already claimed.')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('cannot claim for address other than proof', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await expect(airdrop.claim(1, wallet1.address, 101, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Invalid proof.'
|
|
|
|
|
await expect(distributor.claim(1, wallet1.address, 101, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Invalid proof.'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('cannot claim more than proof', async () => {
|
|
|
|
|
const proof0 = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await expect(airdrop.claim(0, wallet0.address, 101, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Invalid proof.'
|
|
|
|
|
await expect(distributor.claim(0, wallet0.address, 101, proof0, overrides)).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Invalid proof.'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('gas', async () => {
|
|
|
|
|
const proof = tree.getProof(0, wallet0.address, BigNumber.from(100))
|
|
|
|
|
const tx = await airdrop.claim(0, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(0, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
expect(receipt.gasUsed).to.eq(78466)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('larger tree', () => {
|
|
|
|
|
let airdrop: Contract
|
|
|
|
|
let distributor: Contract
|
|
|
|
|
let tree: BalanceTree
|
|
|
|
|
beforeEach('deploy', async () => {
|
|
|
|
|
tree = new BalanceTree(
|
|
|
|
|
@@ -164,40 +188,40 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
return { account: wallet.address, amount: BigNumber.from(ix + 1) }
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
airdrop = await deployContract(wallet0, Airdrop, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(airdrop.address, 201)
|
|
|
|
|
distributor = await deployContract(wallet0, Distributor, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(distributor.address, 201)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('claim index 4', async () => {
|
|
|
|
|
const proof = tree.getProof(4, wallets[4].address, BigNumber.from(5))
|
|
|
|
|
await expect(airdrop.claim(4, wallets[4].address, 5, proof, overrides))
|
|
|
|
|
.to.emit(airdrop, 'Claimed')
|
|
|
|
|
await expect(distributor.claim(4, wallets[4].address, 5, proof, overrides))
|
|
|
|
|
.to.emit(distributor, 'Claimed')
|
|
|
|
|
.withArgs(4, wallets[4].address, 5)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('claim index 9', async () => {
|
|
|
|
|
const proof = tree.getProof(9, wallets[9].address, BigNumber.from(10))
|
|
|
|
|
await expect(airdrop.claim(9, wallets[9].address, 10, proof, overrides))
|
|
|
|
|
.to.emit(airdrop, 'Claimed')
|
|
|
|
|
await expect(distributor.claim(9, wallets[9].address, 10, proof, overrides))
|
|
|
|
|
.to.emit(distributor, 'Claimed')
|
|
|
|
|
.withArgs(9, wallets[9].address, 10)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('gas', async () => {
|
|
|
|
|
const proof = tree.getProof(9, wallets[9].address, BigNumber.from(10))
|
|
|
|
|
const tx = await airdrop.claim(9, wallets[9].address, 10, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(9, wallets[9].address, 10, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
expect(receipt.gasUsed).to.eq(80960)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('gas second down about 15k', async () => {
|
|
|
|
|
await airdrop.claim(
|
|
|
|
|
await distributor.claim(
|
|
|
|
|
0,
|
|
|
|
|
wallets[0].address,
|
|
|
|
|
1,
|
|
|
|
|
tree.getProof(0, wallets[0].address, BigNumber.from(1)),
|
|
|
|
|
overrides
|
|
|
|
|
)
|
|
|
|
|
const tx = await airdrop.claim(
|
|
|
|
|
const tx = await distributor.claim(
|
|
|
|
|
1,
|
|
|
|
|
wallets[1].address,
|
|
|
|
|
2,
|
|
|
|
|
@@ -210,7 +234,7 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('realistic size tree', () => {
|
|
|
|
|
let airdrop: Contract
|
|
|
|
|
let distributor: Contract
|
|
|
|
|
let tree: BalanceTree
|
|
|
|
|
const NUM_LEAVES = 100_000
|
|
|
|
|
const NUM_SAMPLES = 25
|
|
|
|
|
@@ -233,19 +257,19 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
beforeEach('deploy', async () => {
|
|
|
|
|
airdrop = await deployContract(wallet0, Airdrop, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(airdrop.address, constants.MaxUint256)
|
|
|
|
|
distributor = await deployContract(wallet0, Distributor, [token.address, tree.getHexRoot()], overrides)
|
|
|
|
|
await token.setBalance(distributor.address, constants.MaxUint256)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('gas', async () => {
|
|
|
|
|
const proof = tree.getProof(50000, wallet0.address, BigNumber.from(100))
|
|
|
|
|
const tx = await airdrop.claim(50000, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(50000, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
expect(receipt.gasUsed).to.eq(91650)
|
|
|
|
|
})
|
|
|
|
|
it('gas deeper node', async () => {
|
|
|
|
|
const proof = tree.getProof(90000, wallet0.address, BigNumber.from(100))
|
|
|
|
|
const tx = await airdrop.claim(90000, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(90000, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
expect(receipt.gasUsed).to.eq(91586)
|
|
|
|
|
})
|
|
|
|
|
@@ -254,7 +278,7 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
let count: number = 0
|
|
|
|
|
for (let i = 0; i < NUM_LEAVES; i += NUM_LEAVES / NUM_SAMPLES) {
|
|
|
|
|
const proof = tree.getProof(i, wallet0.address, BigNumber.from(100))
|
|
|
|
|
const tx = await airdrop.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
total = total.add(receipt.gasUsed)
|
|
|
|
|
count++
|
|
|
|
|
@@ -268,7 +292,7 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
let count: number = 0
|
|
|
|
|
for (let i = 0; i < 25; i++) {
|
|
|
|
|
const proof = tree.getProof(i, wallet0.address, BigNumber.from(100))
|
|
|
|
|
const tx = await airdrop.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const tx = await distributor.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
const receipt = await tx.wait()
|
|
|
|
|
total = total.add(receipt.gasUsed)
|
|
|
|
|
count++
|
|
|
|
|
@@ -280,9 +304,9 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
it('no double claims in random distribution', async () => {
|
|
|
|
|
for (let i = 0; i < 25; i += Math.floor(Math.random() * (NUM_LEAVES / NUM_SAMPLES))) {
|
|
|
|
|
const proof = tree.getProof(i, wallet0.address, BigNumber.from(100))
|
|
|
|
|
await airdrop.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
await expect(airdrop.claim(i, wallet0.address, 100, proof, overrides)).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Drop already claimed.'
|
|
|
|
|
await distributor.claim(i, wallet0.address, 100, proof, overrides)
|
|
|
|
|
await expect(distributor.claim(i, wallet0.address, 100, proof, overrides)).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Drop already claimed.'
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
@@ -290,7 +314,7 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('parseBalanceMap', () => {
|
|
|
|
|
let airdrop: Contract
|
|
|
|
|
let distributor: Contract
|
|
|
|
|
let claims: {
|
|
|
|
|
[account: string]: {
|
|
|
|
|
index: number
|
|
|
|
|
@@ -306,8 +330,8 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
})
|
|
|
|
|
expect(tokenTotal).to.eq('0x02ee') // 750
|
|
|
|
|
claims = innerClaims
|
|
|
|
|
airdrop = await deployContract(wallet0, Airdrop, [token.address, merkleRoot], overrides)
|
|
|
|
|
await token.setBalance(airdrop.address, tokenTotal)
|
|
|
|
|
distributor = await deployContract(wallet0, Distributor, [token.address, merkleRoot], overrides)
|
|
|
|
|
await token.setBalance(distributor.address, tokenTotal)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('check the proofs is as expected', () => {
|
|
|
|
|
@@ -339,14 +363,14 @@ describe('AirdropTokenDistributor', () => {
|
|
|
|
|
it('all claims work exactly once', async () => {
|
|
|
|
|
for (let account in claims) {
|
|
|
|
|
const claim = claims[account]
|
|
|
|
|
await expect(airdrop.claim(claim.index, account, claim.amount, claim.proof, overrides))
|
|
|
|
|
.to.emit(airdrop, 'Claimed')
|
|
|
|
|
await expect(distributor.claim(claim.index, account, claim.amount, claim.proof, overrides))
|
|
|
|
|
.to.emit(distributor, 'Claimed')
|
|
|
|
|
.withArgs(claim.index, account, claim.amount)
|
|
|
|
|
await expect(airdrop.claim(claim.index, account, claim.amount, claim.proof, overrides)).to.be.revertedWith(
|
|
|
|
|
'AirdropTokenDistributor: Drop already claimed.'
|
|
|
|
|
await expect(distributor.claim(claim.index, account, claim.amount, claim.proof, overrides)).to.be.revertedWith(
|
|
|
|
|
'MerkleDistributor: Drop already claimed.'
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
expect(await token.balanceOf(airdrop.address)).to.eq(0)
|
|
|
|
|
expect(await token.balanceOf(distributor.address)).to.eq(0)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|