Cashdrop Covenant (Non-merchant linked)

This covenant contains the BCH that users collect. Version 1 cashdrop covenants belong to a quest that was not linked to a merchant during creation. For these types of covenants, only a BCH reward is given to the collector.

PARAMETERS

NameTypeDescription
cashdropLATintLatitude coordinate of the cashdrop. Since CashScript does not support decimals, this 5-decimal precision location is converted to an int by multiplying it by 100,000.
cashdropLONintLongitude coordinate of the cashdrop. Since CashScript does not support decimals, this 5-decimal precision location is converted to an int by multiplying it by 100,000.
amountintThe BCH reward amount that gets sent to a collector.
expirationTimestampintThe timestamp when the uncollected cashdrop will be refunded.
questFunderPKHbytes20The cashdrop’s quest funder’s public key hash, where the cashdrop reward will be refunded after expiration.

FUNCTIONS

  • refund = used to refund the funds to the quest funder in case of a server or network error during distribution. The amount refunded is the original quest amount subtracted by the transaction fee (dust).

Parameters:

None

  • collect = the main function for verifying and sending the BCH reward to the collector. It first checks if the user is truly inside the cashdrop’s collect radius before it sends the reward.

Parameters:

NameTypeDescription
collectorLATintLatitude coordinate of the collector. Since CashScript does not support decimals, this 5-decimal precision location is converted to an int by multiplying it by 100,000.
collectorLONintLongitude coordinate of the collector. Since CashScript does not support decimals, this 5-decimal precision location is converted to an int by multiplying it by 100,000.
collectRadiusintThe current cashdrop radius range for collection.
collectorPKHbytes20The collector’s public key hash, where the BCH reward will be sent to.

CONTRACT SCRIPT

pragma cashscript ^0.8.0;

contract CashDropCovenant (
    int cashdropLAT,          // latitude of cashdrop
    int cashdropLON,          // longitude of cashdrop
    int amount,               // total BCH amount reward
    int expirationTimestamp,  // uncollected cashdrop expiration time since quest was created
    bytes20 questFunderPKH,    // quest funder's pubkey hash
) {
    /**
        Refund cashdrop reward to quest owner after expiry date.
        Expiration date is X days after quest date of funding
     */
    function refund () {
        require(tx.time >= expirationTimestamp);
        require(tx.outputs[0].value == amount);

        bytes25 ownerLock = new LockingBytecodeP2PKH(questFunderPKH);
        require(tx.outputs[0].lockingBytecode == ownerLock);
    }

    /**
        Verifies if collector is within collection radius
     */
    function collect (
        int collectorLAT,       // latitude of collector during collection
        int collectorLON,       // longitude of collector during collection
        int collectRadius,      // cashdrop range where a user can collect a cashdrop
        bytes20 collectorPKH    // collector's pubkey hash
    ) {
        require(tx.outputs[0].value == amount);

        bytes25 collectorLock = new LockingBytecodeP2PKH(collectorPKH);
        require(tx.outputs[0].lockingBytecode == collectorLock);

        /**
            calculate distance between collector and cashdrop locations
            using trigonometric functions alternatives since trig funcs arent
            supported on cashscript
         */
        int cashdropLATP = cashdropLAT + 9000000;
        int collectorLATP = collectorLAT + 9000000;
        int cashdropLONP = cashdropLON + 18000000;
        int collectorLONP = collectorLON + 18000000;

        int X1 = collectorLONP - cashdropLONP;
        int X2 = abs(X1);
        int mod = X2 % 10;
        
        if (mod < 5) {
            X2 = X2 - mod;
        } else {
            X2 = (X2 - mod) + 10;
        }

        int X3_1 = X2 / 10;
        int X3_2 = X2 - 360;
        int X4 = abs(X3_2) / 10;

        int Y1 = abs(collectorLATP - cashdropLATP);

        int Z1 = max(X3_1, Y1);
        int Z2 = max(X4, Y1);
        
        int calculatedDistance = min(Z2, Z1);

        require(calculatedDistance <= collectRadius);
    }
}