使用 sCrypt 实现定期支付合约

这里我们介绍一个定期支付合约,允许用户定期存入款项,并且收款者可以定期收取款项。

subscription

合约实现

合约代码如下:


contract Recurring {
    Ripemd160 userPubKeyHash; //Address of the owner of the coin
    int merchantPayment; //How much the merchant can take from the contract
    Ripemd160 merchantPubKeyHash; //Address of the merchant
    int frequenceOfPayment; //Merchant can take money each "frequenceOfPayment" seconds

    // User can deposit more money in his recurring contract
    public function deposit_user(SigHashPreimage preImage, int depositAmount, int changeAmount) {
        require(Tx.checkPreimage(preImage));
        require(depositAmount > 0);
        int contractTotalAmount = SigHash.value(preImage) + depositAmount;
        bytes output = Utils.buildOutput(SigHash.scriptCode(preImage), contractTotalAmount);
        bytes change_output = changeAmount <= 546 ? b'' : Utils.buildOutput(Utils.buildPublicKeyHashScript(this.userPubKeyHash), changeAmount);
        require(hash256(output + change_output) == SigHash.hashOutputs(preImage));
    }

    // User wants to withdraw its money. Standard P2PKH transaction
    public function withdraw_user(Sig sig, PubKey pubKey) {
        require(hash160(pubKey) == this.userPubKeyHash);
        require(checkSig(sig, pubKey));
    }

    // Merchant wants its money
    public function withdraw_merchant(SigHashPreimage preImage, int newAmount) {
        require(Tx.checkPreimage(preImage));
        //Output for the merchant
        bytes outputMerchant = Utils.buildOutput(Utils.buildPublicKeyHashScript(this.merchantPubKeyHash), this.merchantPayment);
        //Output that'll be the next instance of the contract
        //Check nlocktime
        bytes scriptCode = SigHash.scriptCode(preImage);
        int scriptLen = len(scriptCode);
        bytes codePart = this.getCodePart(scriptCode, scriptLen);
        int newMatureTime = this.getPrevMatureTime(scriptCode, scriptLen) + this.frequenceOfPayment;
        bytes newScript = codePart + pack(newMatureTime);
        require(SigHash.nLocktime(preImage) == newMatureTime);
        //Build the output
        bytes outputContract = Utils.buildOutput(newScript, newAmount);
        require(hash256(outputContract + outputMerchant) == SigHash.hashOutputs(preImage));
    }

    function getPrevMatureTime(bytes lockingScript, int scriptLen) : int {
        return unpack(lockingScript[scriptLen - 4 :]);
    }

    function getCodePart(bytes lockingScript, int scriptLen) : bytes {
        return lockingScript[0 : scriptLen - 4];
    }
}

该合约有3个公共函数:

  • 第一个允许用户存入更多的钱;
  • 第二个允许用户随时选择退出。 请注意,如果用户需要在停止重复付款之前提供取消通知给商家,可以基于此合约进行些小的修改而实现;
  • 最后一个允许商家定期从合约中提取一定数量的钱。 它包含一个nLockTimeVerify 部分,以防止商家立即提取它。另请注意,nLockTimeVerify 仅适用于商家,用户仍可以存入更多资金或选择退出。

应用场景

此合约除了对于订阅付款非常有用以外,其设计思路也可以用于实现很多支付帐户的功能,例如:每天有支出限额;或者如果手机被盗会紧急关闭;有取款密码;支付时需要满足特殊条件等应用场景。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sCrypt Web3应用开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值