Created
December 9, 2020 09:03
-
-
Save ccoincash/fafb5e7097a04fb4dbb9bcd79273d8f6 to your computer and use it in GitHub Desktop.
a token contract support pay to contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "util.scrypt"; | |
import "backtrace.scrypt"; | |
/** | |
* A token protocol based on UTXO model | |
*/ | |
contract Token { | |
public function split( | |
SigHashPreimage txPreimage, | |
PubKey senderPubKey, | |
Sig senderSig, | |
Ripemd160 receiver0, | |
int tokenAmount0, | |
int satoshiAmount0, | |
Ripemd160 receiver1, | |
int tokenAmount1, | |
int satoshiAmount1 | |
) { | |
require(tokenAmount0 > 0); | |
// 1 to 1 transfer when tokenAmount1 is 0 | |
require(tokenAmount1 >= 0); | |
// this ensures the preimage is for the current tx | |
require(Tx.checkPreimage(txPreimage)); | |
// read previous locking script | |
// locking script = codePart + OP_RETURN + senderAddress + balance | |
bytes lockingScript = Util.scriptCode(txPreimage); | |
int scriptLen = len(lockingScript); | |
int dataStart = scriptLen - Util.PubKeyHashLen - 8; | |
Ripemd160 senderAddress = Ripemd160(lockingScript[dataStart: dataStart + Util.PubKeyHashLen]); | |
// authorize | |
require(hash160(senderPubKey) == senderAddress); | |
require(checkSig(senderSig, senderPubKey)); | |
int senderBalance = Util.fromLEUnsigned(lockingScript[dataStart + Util.PubKeyHashLen: dataStart + Util.PubKeyHashLen + 8]); | |
// split | |
require(senderBalance == tokenAmount0 + tokenAmount1); | |
// persist contract code part, including op_return itself | |
bytes codePart = lockingScript[: dataStart]; | |
// setting first balance as 0 is just a convention, not a requirement | |
bytes outputScript0 = codePart + receiver0 + num2bin(tokenAmount0, 8); | |
bytes output0 = Util.buildOutput(outputScript0, satoshiAmount0); | |
bytes outputScript1 = codePart + receiver1 + num2bin(tokenAmount1, 8); | |
bytes output1 = (tokenAmount1 > 0) ? Util.buildOutput(outputScript1, satoshiAmount1) : b''; | |
Sha256 hashOutputs = hash256(output0 + output1); | |
require(hashOutputs == Util.hashOutputs(txPreimage)); | |
} | |
public function unlockFromScriptHash( | |
SigHashPreimage txPreimage, | |
bytes prevouts, | |
bytes prevScriptTx, | |
int prevScriptOutIndex, | |
Ripemd160 receiver | |
) { | |
SigHashType sigHashType = SigHash.SINGLE | SigHash.FORKID; | |
require(Util.checkPreimageSigHashType(txPreimage, sigHashType)); | |
// check prevouts | |
require(hash256(prevouts) == Util.hashPrevouts(txPreimage)); | |
// verify the prevScriptTx | |
// the script input index is 0 | |
int outpointLen = 36; | |
bytes prevScriptTxId = prevouts[:32]; | |
require(hash256(prevScriptTx) == prevScriptTxId); | |
// check the script | |
bytes lockingScript = Util.scriptCode(txPreimage); | |
int scriptLen = len(lockingScript); | |
int dataStart = scriptLen - Util.PubKeyHashLen - 8; | |
Ripemd160 scriptHash = Ripemd160(lockingScript[dataStart: dataStart + Util.PubKeyHashLen]); | |
bytes prevScriptCode = Backtrace.readOutputScript(prevScriptTx, prevScriptOutIndex); | |
require(hash160(prevScriptCode) == scriptHash); | |
// check the output | |
bytes codePart = lockingScript[: dataStart]; | |
int tokenAmount = unpack(lockingScript[dataStart + Util.PubKeyHashLen: dataStart + Util.PubKeyHashLen + 8]); | |
int satoshiAmount = Util.value(txPreimage); | |
// setting first balance as 0 is just a convention, not a requirement | |
bytes outputScript = codePart + receiver + num2bin(tokenAmount, 8); | |
bytes output = Util.buildOutput(outputScript, satoshiAmount); | |
Sha256 hashOutputs = hash256(output); | |
require(hashOutputs == Util.hashOutputs(txPreimage)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment