I'm trying to create a simple airDrop contract. But whatever I do nothing seems to work.

I based my custom contract and token of the zeppelin-solidity contracts.

This is the code I'm using to airdrop funds:

function distribute(
    uint _airDropID
) public
    for (uint i = 0; i < airDrops[_airDropID].participantCount; i++) {
        TokenDrop(msg.sender, airDrops[_airDropID].participants[i], airDrops[_airDropID].amount);

        ERC20(token).transfer(airDrops[_airDropID].participants[i], airDrops[_airDropID].amount);

        //token.mint(airDrops[_airDropID].participants[i], airDrops[_airDropID].amount);

I also tried to mint the funds but both functions result in a VM Exception while processing transaction: revert

Which tells me a require() is failing. I tried further debugging my code and it seemed that the msg.sender address changed during the transfer() or mint() function.

This is the test I'm currently executing.

let AirDrop = artifacts.require("./AirDrop.sol");
let GameToken = artifacts.require("./GameToken.sol");

let gameTokenMarketCap = 1*1000*1000*1000;
let amountToMint = 1*1000*1000;
let amountToApprove = 1*1000*1000*1000*1000;
let amountToDrop = 1000;
let airDropParticipants = 2;

//Expected Test Results
let expectedAirDropID = 0;

contract('Airdrop', (accounts) => {
    let tokenContract;
    let airDropContract;
    let participantID;
    let dropper = accounts[0];
    let receiver = accounts[1];
    let receiver2 = accounts[2];

     * Initial setup. 
     * Mint tokens to dropper address and check it.
    before(() => {
        return GameToken.new(gameTokenMarketCap, dropper, {from: dropper}).then((instance) => {
            tokenContract = instance;

            return AirDrop.new(tokenContract.address, dropper, {from: dropper});
        }).then((instance) => {
            airDropContract = instance;

            return tokenContract.mint(dropper, amountToMint).then(() => {
                return tokenContract.balanceOf.call(dropper);
            }).then((balance) => {
                assert.equal(balance.valueOf(), amountToMint, "Token dropper balance should equal minted balance!");

    describe('Creation and Execution', () => {
        let airDropID;

        it('Allows creating an airDrop and increments the ID', async () => {
            //Firstly test with .call
            airDropContract.createAirDrop.call(airDropParticipants, amountToDrop).then((airDrop) => {
                airDropID = airDrop;

                assert.equal(airDropID.valueOf(), expectedAirDropID, "AirDrop ID not correctly created!");

            //Execute on blockchain
            await airDropContract.createAirDrop(airDropParticipants, amountToDrop);

            return true;

        //Add an participant to the created airDrop
        it('Allows adding a participant to the AirDrop', () => {
            airDropContract.addParticipantToAirDrop.call(airDropID, receiver).then(participantID => {
                assert.equal(participantID.valueOf(), expectedAirDropID, "Participant ID not correctly created!");

            airDropContract.addParticipantToAirDrop(airDropID, receiver);
            airDropContract.addParticipantToAirDrop(airDropID, receiver2);

            return true;

        it('Allows distributing an airDrop and sends the right amount of credits to both participants', async () => {
            //Distribute and check the airDrop
            return airDropContract.distribute(airDropID, {from: dropper}).then(success => {
                return tokenContract.balanceOf.call(receiver);
            }).then(balance => {
                assert.equal(balance.valueOf(), amountToDrop, "airDrop was not executed correctly.");

                return tokenContract.balanceOf.call(receiver2);
            }).then((balance) => {
                assert.equal(balance.valueOf(), amountToDrop, "airDrop was not executed correctly.");

                return tokenContract.balanceOf.call(dropper);
            }).then((balance) => {
                assert.equal(balance.valueOf(), amountToMint - amountToDrop * 2);

                return true;

This is the failing function: airDropContract.distribute(airDropID, {from: dropper})

Does anyone know why the value of msg.sender is changing and why the airdrop isn't working?

Thanks in advance.

1 Answer 1


Solved, I had to approve the contract to send tokens on my behalf.

tokenContract.approve(airDropContract.address, amountToApprove);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.