public bool DeployContractScript(StorageContext storage, Address contractOwner, string name, Address contractAddress, byte[] script, ContractInterface abi) { var scriptKey = GetContractKey(contractAddress, "script"); if (storage.Has(scriptKey)) { return(false); } storage.Put(scriptKey, script); var ownerBytes = contractOwner.ToByteArray(); var ownerKey = GetContractKey(contractAddress, "owner"); storage.Put(ownerKey, ownerBytes); var abiBytes = abi.ToByteArray(); var abiKey = GetContractKey(contractAddress, "abi"); storage.Put(abiKey, abiBytes); var nameBytes = Encoding.ASCII.GetBytes(name); var nameKey = GetContractKey(contractAddress, "name"); storage.Put(nameKey, nameBytes); var contractList = new StorageList(GetContractListKey(), storage); contractList.Add <Address>(contractAddress); return(true); }
public void UpgradeContract(StorageContext storage, string name, byte[] script, ContractInterface abi) { if (Nexus.IsNativeContract(name) || ValidationUtils.IsValidTicker(name)) { throw new ChainException($"Cannot upgrade this type of contract: {name}"); } if (!IsContractDeployed(storage, name)) { throw new ChainException($"Cannot upgrade non-existing contract: {name}"); } var address = SmartContract.GetAddressForName(name); var scriptKey = GetContractKey(address, "script"); storage.Put(scriptKey, script); var abiKey = GetContractKey(address, "abi"); var abiBytes = abi.ToByteArray(); storage.Put(abiBytes, abiBytes); }
public Transaction GenerateToken(PhantasmaKeys owner, string symbol, string name, BigInteger totalSupply, int decimals, TokenFlags flags, byte[] tokenScript = null, Dictionary <string, int> labels = null, IEnumerable <ContractMethod> customMethods = null) { var version = Nexus.GetGovernanceValue(Nexus.RootStorage, Nexus.NexusProtocolVersionTag); if (labels == null) { labels = new Dictionary <string, int>(); } if (tokenScript == null) { // small script that restricts minting of tokens to transactions where the owner is a witness var addressStr = Base16.Encode(owner.Address.ToByteArray()); string[] scriptString; if (version >= 4) { scriptString = new string[] { $"alias r3, $result", $"alias r4, $owner", $"@{AccountTrigger.OnMint}: nop", $"load $owner 0x{addressStr}", "push $owner", "extcall \"Address()\"", "extcall \"Runtime.IsWitness\"", "pop $result", $"jmpif $result, @end", $"load r0 \"invalid witness\"", $"throw r0", $"@end: ret" }; } else { scriptString = new string[] { $"alias r1, $triggerMint", $"alias r2, $currentTrigger", $"alias r3, $result", $"alias r4, $owner", $@"load $triggerMint, ""{AccountTrigger.OnMint}""", $"pop $currentTrigger", $"equal $triggerMint, $currentTrigger, $result", $"jmpif $result, @mintHandler", $"jmp @end", $"@mintHandler: nop", $"load $owner 0x{addressStr}", "push $owner", "extcall \"Address()\"", "extcall \"Runtime.IsWitness\"", "pop $result", $"jmpif $result, @end", $"load r0 \"invalid witness\"", $"throw r0", $"@end: ret" }; } DebugInfo debugInfo; tokenScript = AssemblerUtils.BuildScript(scriptString, "GenerateToken", out debugInfo, out labels); } var sb = ScriptUtils. BeginScript(). AllowGas(owner.Address, Address.Null, MinimumFee, 9999); if (version >= 4) { var triggerMap = new Dictionary <AccountTrigger, int>(); var onMintLabel = AccountTrigger.OnMint.ToString(); if (labels.ContainsKey(onMintLabel)) { triggerMap[AccountTrigger.OnMint] = labels[onMintLabel]; } var methods = AccountContract.GetTriggersForABI(triggerMap); if (customMethods != null) { methods = methods.Concat(customMethods); } var abi = new ContractInterface(methods, Enumerable.Empty <ContractEvent>()); var abiBytes = abi.ToByteArray(); sb.CallInterop("Nexus.CreateToken", owner.Address, symbol, name, totalSupply, decimals, flags, tokenScript, abiBytes); } else { sb.CallInterop("Nexus.CreateToken", owner.Address, symbol, name, totalSupply, decimals, flags, tokenScript); } if (!flags.HasFlag(TokenFlags.Fungible)) { ContractInterface nftABI; byte[] nftScript; NFTUtils.GenerateNFTDummyScript(symbol, name, name, "http://simulator/nft/*", "http://simulator/img/*", out nftScript, out nftABI); sb.CallInterop("Nexus.CreateTokenSeries", owner.Address, symbol, new BigInteger(0), totalSupply, TokenSeriesMode.Unique, nftScript, nftABI.ToByteArray()); } sb.SpendGas(owner.Address); var script = sb.EndScript(); var tx = MakeTransaction(owner, ProofOfWork.Minimal, Nexus.RootChain, script); return(tx); }
static byte[] GenCreateToken() { Console.Write("Token symbol? "); string symbol = Console.ReadLine(); if (!ValidationUtils.IsValidTicker(symbol)) { Console.Write("Invalid token symbol"); return(null); } Console.Write("Token name? "); string name = Console.ReadLine(); TokenFlags flags = TokenFlags.Transferable; var possibleValues = new[] { TokenFlags.Burnable, TokenFlags.Divisible, TokenFlags.Finite, TokenFlags.Fungible }; foreach (var val in possibleValues) { if (FetchAnswer($"Is {symbol} {val}?")) { flags |= val; } } int decimals; if (flags.HasFlag(TokenFlags.Divisible)) { Console.Write($"How many decimals {symbol} has?: "); if (!int.TryParse(Console.ReadLine(), out decimals) || decimals < 0 || decimals > 18) { Console.Write("Invalid decimals"); return(null); } } else { decimals = 0; } BigInteger maxSupply; if (flags.HasFlag(TokenFlags.Finite)) { Console.Write($"What is the max supply of {symbol}?: "); decimal val; if (!decimal.TryParse(Console.ReadLine(), out val) || val <= 0) { Console.Write("Invalid decimals"); return(null); } maxSupply = UnitConversion.ToBigInteger(val, decimals); } else { maxSupply = 0; } var labels = new Dictionary <string, int>(); var addressStr = Base16.Encode(signerKeys.Address.ToByteArray()); string[] scriptString; scriptString = new string[] { $"alias r3, $result", $"alias r4, $owner", $"@{AccountTrigger.OnMint}: nop", $"load $owner 0x{addressStr}", "push $owner", "extcall \"Address()\"", "extcall \"Runtime.IsWitness\"", "pop $result", $"jmpif $result, @end", $"load r0 \"invalid witness\"", $"throw r0", $"@end: ret" }; DebugInfo debugInfo; var tokenScript = AssemblerUtils.BuildScript(scriptString, "GenerateToken", out debugInfo, out labels); var sb = ScriptUtils. BeginScript(). AllowGas(signerKeys.Address, Address.Null, MinimumFee, 9999); var triggerMap = new Dictionary <AccountTrigger, int>(); var onMintLabel = AccountTrigger.OnMint.ToString(); if (labels.ContainsKey(onMintLabel)) { triggerMap[AccountTrigger.OnMint] = labels[onMintLabel]; } var methods = AccountContract.GetTriggersForABI(triggerMap); var abi = new ContractInterface(methods, Enumerable.Empty <ContractEvent>()); var abiBytes = abi.ToByteArray(); sb.CallInterop("Nexus.CreateToken", signerKeys.Address, symbol, name, maxSupply, decimals, flags, tokenScript, abiBytes); if (!flags.HasFlag(TokenFlags.Fungible)) { Console.Write("NFT deployment not supported yet"); return(null); } sb.SpendGas(signerKeys.Address); var script = sb.EndScript(); return(script); }