import "cat20Proto.scrypt";import "../utils/stateUtils.scrypt";import "../utils/backtrace.scrypt";import "../utils/sigHashUtils.scrypt";import "guardProto.scrypt";import "../utils/txProof.scrypt"; struct TokenUnlockArgs { bool isUserSpend; bytes userPubKeyPrefix; PubKey userPubKey; Sig userSig; int contractInputIndex; } struct GuardInfo { XrayedTxIdPreimg3 tx; int inputIndexVal; bytes outputIndex; GuardConstState guardState; } contract CAT20 { bytes minterScript; bytes guardScript; public function unlock(TokenUnlockArgs tokenUnlockArgs, CAT20State preState, PreTxStatesInfo preTxStatesInfo, GuardInfo guardInfo, BacktraceInfo backtraceInfo, SHPreimage shPreimage, PrevoutsCtx prevoutsCtx, bytes[6] spentScriptsCtx) { require(checkSig(SigHashUtils.checkSHPreimage(shPreimage), SigHashUtils.Gx)); SigHashUtils.checkPrevoutsCtx(prevoutsCtx, shPreimage.hashPrevouts, shPreimage.inputIndex); SigHashUtils.checkSpentScriptsCtx(spentScriptsCtx, shPreimage.hashSpentScripts); StateUtils.verifyPreStateHash(preTxStatesInfo, CAT20Proto.stateHash(preState), backtraceInfo.preTx.outputScriptList[0], prevoutsCtx.outputIndexVal); bytes preScript = spentScriptsCtx[(prevoutsCtx.inputIndexVal)]; Backtrace.verifyToken(prevoutsCtx.spentTxhash, backtraceInfo, this.minterScript, preScript); this.valitateGuard(guardInfo, preScript, preState, prevoutsCtx.inputIndexVal, prevoutsCtx.prevouts, spentScriptsCtx); if(tokenUnlockArgs.isUserSpend) { require(hash160(tokenUnlockArgs.userPubKeyPrefix + tokenUnlockArgs.userPubKey) == preState.ownerAddr); require(checkSig(tokenUnlockArgs.userSig, tokenUnlockArgs.userPubKey)); } else { require(preState.ownerAddr == hash160(spentScriptsCtx[(tokenUnlockArgs.contractInputIndex)])); } require(true); } function valitateGuard(GuardInfo guardInfo, bytes preScript, CAT20State preState, int inputIndexVal, bytes[6] prevouts, bytes[6] spentScriptsCtx) : bool { bytes guardHashRoot = GuardProto.stateHash(guardInfo.guardState); require(guardInfo.guardState.tokenScript == preScript); require(StateUtils.getStateScript(guardHashRoot, 1) == guardInfo.tx.outputScriptList[0]); require(preState.amount > 0); require(guardInfo.guardState.inputTokenAmountArray[(inputIndexVal)] == preState.amount); bytes guardTxid = TxProof.getTxIdFromPreimg3(guardInfo.tx); require(prevouts[(guardInfo.inputIndexVal)] == guardTxid + guardInfo.outputIndex); require(spentScriptsCtx[(guardInfo.inputIndexVal)] == this.guardScript); return true; } }