使用 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 = Util.value(preImage) + depositAmount;
        bytes output = Util.buildOutput(Util.scriptCode(preImage), contractTotalAmount);
        bytes change_output = changeAmount <= 546 ? b'' : Util.buildOutput(Util.buildPublicKeyHashScript(this.userPubKeyHash), changeAmount);
        require(hash256(output + change_output) == Util.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) {
        require(Tx.checkPreimage(preImage));
        //Output for the merchant
        bytes outputMerchant = Util.buildOutput(Util.buildPublicKeyHashScript(this.merchantPubKeyHash), this.merchantPayment);
        //Output that'll be the next instance of the contract
        //Check nlocktime
        bytes scriptCode = Util.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(Util.nLocktime(preImage) == newMatureTime);
        //Build the output
        int fee = 5000;
        int contractTotalAmount = Util.value(preImage) - this.merchantPayment - fee;
        bytes outputContract = Util.buildOutput(newScript, contractTotalAmount);
        require(hash256(outputContract + outputMerchant) == Util.hashOutputs(preImage));
    }
}

该合约有3个公共函数:

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

应用场景

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

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页