private static ExecutionState Runtime_TransferTokens(RuntimeVM Runtime) { ExpectStackSize(Runtime, 4); VMObject temp; var source = PopAddress(Runtime); var destination = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Number, "expected number for amount"); var amount = temp.AsNumber(); Runtime.TransferTokens(symbol, source, destination, amount); return(ExecutionState.Running); }
private static ExecutionState Runtime_WriteToken(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Number, "expected number for token ID"); var tokenID = temp.AsNumber(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for ram"); var ram = temp.AsByteArray(); Runtime.WriteToken(symbol, tokenID, ram); return(ExecutionState.Running); }
private static ExecutionState Runtime_Notify(RuntimeVM vm) { vm.Expect(vm.CurrentContext.Name != VirtualMachine.EntryContextName, "cannot notify in current context"); var kind = vm.Stack.Pop().AsEnum <EventKind>(); var address = vm.PopAddress(); var obj = vm.Stack.Pop(); var bytes = obj.Serialize(); vm.Notify(kind, address, bytes); return(ExecutionState.Running); }
private static TokenContent Runtime_ReadTokenInternal(RuntimeVM vm) { vm.ExpectStackSize(2); var symbol = vm.PopString("symbol"); var tokenID = vm.PopNumber("token ID"); var result = vm.ReadToken(symbol, tokenID); vm.Expect(result.TokenID == tokenID, "retrived NFT content does not have proper tokenID"); return(result); }
private static ExecutionState Runtime_ReadToken(RuntimeVM Runtime) { ExpectStackSize(Runtime, 2); VMObject temp; temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Number, "expected number for token ID"); var tokenID = temp.AsNumber(); var content = Runtime.ReadToken(symbol, tokenID); var result = new VMObject(); result.SetValue(content.RAM, VMType.Bytes); Runtime.Stack.Push(result); return(ExecutionState.Running); }
private static TokenContent Runtime_ReadTokenInternal(RuntimeVM Runtime) { ExpectStackSize(Runtime, 2); VMObject temp; temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var tokenID = PopNumber(Runtime, "token ID"); return(Runtime.ReadToken(symbol, tokenID)); }
private static ExecutionState Runtime_BurnTokens(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var amount = PopNumber(Runtime, "amount"); if (Runtime.Nexus.HasGenesis) { Runtime.Expect(symbol != DomainSettings.FuelTokenSymbol && symbol != DomainSettings.StakingTokenSymbol, "cannot mint system tokens after genesis"); } Runtime.BurnTokens(symbol, source, amount); return(ExecutionState.Running); }
private static ExecutionState Runtime_TransferBalance(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; var source = PopAddress(Runtime); var destination = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var token = Runtime.GetToken(symbol); Runtime.Expect(token.IsFungible(), "must be fungible"); var amount = Runtime.GetBalance(symbol, source); Runtime.TransferTokens(symbol, source, destination, amount); return(ExecutionState.Running); }
private static ExecutionState Runtime_SwapTokens(RuntimeVM vm) { vm.ExpectStackSize(5); VMObject temp; temp = vm.Stack.Pop(); vm.Expect(temp.Type == VMType.String, "expected string for target chain"); var targetChain = temp.AsString(); var source = vm.PopAddress(); var destination = vm.PopAddress(); temp = vm.Stack.Pop(); vm.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var value = vm.PopNumber("amount"); vm.SwapTokens(vm.Chain.Name, source, targetChain, destination, symbol, value); return(ExecutionState.Running); }
private static ExecutionState Runtime_CreateChain(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for organization"); var org = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for name"); var name = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for parent"); var parentName = temp.AsString(); Runtime.CreateChain(source, org, name, parentName); return(ExecutionState.Running); }
private static ExecutionState Runtime_CreateOrganization(RuntimeVM Runtime) { ExpectStackSize(Runtime, 4); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for ID"); var ID = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for name"); var name = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for script"); var script = temp.AsByteArray(); Runtime.CreateOrganization(source, ID, name, script); return(ExecutionState.Running); }
private static ExecutionState Data_Get(RuntimeVM runtime) { var key = runtime.Stack.Pop(); var key_bytes = key.AsByteArray(); runtime.Expect(key_bytes.Length > 0, "invalid key"); var value_bytes = runtime.Storage.Get(key_bytes); var val = new VMObject(); val.SetValue(value_bytes, VMType.Bytes); runtime.Stack.Push(val); return(ExecutionState.Running); }
public bool RemoveMember(RuntimeVM Runtime, Address from, Address target) { Runtime.Expect(Runtime.IsRootChain(), "must be root chain"); var list = GetMemberList(); if (!list.Contains <Address>(target)) { return(false); } list.Remove <Address>(target); Runtime.Notify(EventKind.OrganizationRemove, from, new OrganizationEventData(this.ID, target)); return(true); }
private static ExecutionState Runtime_CreateToken(RuntimeVM Runtime) { ExpectStackSize(Runtime, 9); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for name"); var name = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for platform"); var platform = temp.AsString(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for hash"); var hash = Serialization.Unserialize <Hash>(temp.AsByteArray()); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Number, "expected number for maxSupply"); var maxSupply = temp.AsNumber(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Number, "expected number for decimals"); var decimals = (int)temp.AsNumber(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Enum, "expected enum for flags"); var flags = temp.AsEnum <TokenFlags>(); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.Bytes, "expected bytes for script"); var script = temp.AsByteArray(); Runtime.CreateToken(source, symbol, name, platform, hash, maxSupply, decimals, flags, script); return(ExecutionState.Running); }
private static ExecutionState Data_Delete(RuntimeVM vm) { vm.ExpectStackSize(1); // for security reasons we don't accept the caller to specify a contract name var contractName = vm.CurrentContext.Name; vm.Expect(vm.ContractDeployed(contractName), $"contract {contractName} is not deployed"); var field = vm.PopString("field"); var key = SmartContract.GetKeyForField(contractName, field, false); var contractAddress = SmartContract.GetAddressForName(contractName); vm.CallNativeContext(NativeContractKind.Storage, nameof(StorageContract.DeleteData), contractAddress, key); return(ExecutionState.Running); }
private static ExecutionState Organization_AddMember(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for name"); var name = temp.AsString(); var target = PopAddress(Runtime); Runtime.AddMember(name, source, target); return(ExecutionState.Running); }
private static ExecutionState Runtime_BurnToken(RuntimeVM Runtime) { ExpectStackSize(Runtime, 3); VMObject temp; var source = PopAddress(Runtime); temp = Runtime.Stack.Pop(); Runtime.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var tokenID = PopNumber(Runtime, "token ID"); Runtime.BurnToken(symbol, source, tokenID); return(ExecutionState.Running); }
private static ExecutionState Runtime_TokenExists(RuntimeVM vm) { vm.ExpectStackSize(1); var temp = vm.Stack.Pop(); vm.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var success = vm.TokenExists(symbol); var result = new VMObject(); result.SetValue(success); vm.Stack.Push(result); return(ExecutionState.Running); }
private static ExecutionState Runtime_TransferToken(RuntimeVM vm) { vm.ExpectStackSize(4); VMObject temp; var source = vm.PopAddress(); var destination = vm.PopAddress(); temp = vm.Stack.Pop(); vm.Expect(temp.Type == VMType.String, "expected string for symbol"); var symbol = temp.AsString(); var tokenID = vm.PopNumber("token ID"); vm.TransferToken(symbol, source, destination, tokenID); return(ExecutionState.Running); }
private static ExecutionState Runtime_TransferBalance(RuntimeVM vm) { vm.ExpectStackSize(3); var source = vm.PopAddress(); var destination = vm.PopAddress(); var symbol = vm.PopString("symbol"); var token = vm.GetToken(symbol); vm.Expect(token.IsFungible(), "must be fungible"); var amount = vm.GetBalance(symbol, source); vm.TransferTokens(symbol, source, destination, amount); return(ExecutionState.Running); }
private static ExecutionState Runtime_MintTokens(RuntimeVM vm) { vm.ExpectStackSize(4); var source = vm.PopAddress(); var destination = vm.PopAddress(); var symbol = vm.PopString("symbol"); var amount = vm.PopNumber("amount"); if (vm.Nexus.HasGenesis) { var isMinter = vm.IsMintingAddress(source, symbol); vm.Expect(isMinter, $"{source} is not a valid minting address for {symbol}"); } vm.MintTokens(symbol, source, destination, amount); return(ExecutionState.Running); }
private static ExecutionState Map_Remove(RuntimeVM vm) { vm.ExpectStackSize(2); // for security reasons we don't accept the caller to specify a contract name var contractName = vm.CurrentContext.Name; var field = vm.PopString("field"); var mapKey = SmartContract.GetKeyForField(contractName, field, false); var entry_obj = vm.Stack.Pop(); var entryKey = entry_obj.AsByteArray(); vm.Expect(entryKey.Length > 0, "invalid entry key"); var map = new StorageMap(mapKey, vm.Storage); map.Remove <byte[]>(entryKey); return(ExecutionState.Running); }
private static ExecutionState Runtime_UpgradeContract(RuntimeVM vm) { var tx = vm.Transaction; Throw.IfNull(tx, nameof(tx)); var pow = tx.Hash.GetDifficulty(); vm.Expect(pow >= (int)ProofOfWork.Minimal, "expected proof of work"); vm.ExpectStackSize(1); var from = vm.PopAddress(); vm.Expect(from.IsUser, "address must be user"); vm.Expect(vm.IsStakeMaster(from), "needs to be master"); vm.Expect(vm.IsWitness(from), "invalid witness"); var contractName = vm.PopString("contractName"); var contractAddress = SmartContract.GetAddressForName(contractName); var deployed = vm.Chain.IsContractDeployed(vm.Storage, contractAddress); vm.Expect(deployed, $"{contractName} does not exist"); byte[] script; ContractInterface abi; bool isNative = Nexus.IsNativeContract(contractName); vm.Expect(!isNative, "cannot upgrade native contract"); bool isToken = ValidationUtils.IsValidTicker(contractName); script = vm.PopBytes("contractScript"); var abiBytes = vm.PopBytes("contractABI"); abi = ContractInterface.FromBytes(abiBytes); var fuelCost = vm.GetGovernanceValue(Nexus.FuelPerContractDeployTag); // governance value is in usd fiat, here convert from fiat to fuel amount fuelCost = vm.GetTokenQuote(DomainSettings.FiatTokenSymbol, DomainSettings.FuelTokenSymbol, fuelCost); // burn the "cost" tokens vm.BurnTokens(DomainSettings.FuelTokenSymbol, from, fuelCost); // ABI validation ValidateABI(vm, contractName, abi, isNative); SmartContract oldContract; if (isToken) { oldContract = vm.Nexus.GetTokenContract(vm.Storage, contractName); } else { oldContract = vm.Chain.GetContractByName(vm.Storage, contractName); } vm.Expect(oldContract != null, "could not fetch previous contract"); vm.Expect(abi.Implements(oldContract.ABI), "new abi does not implement all methods of previous abi"); vm.Expect(vm.InvokeTrigger(false, script, contractName, abi, AccountTrigger.OnUpgrade.ToString(), from) == TriggerResult.Success, "OnUpgrade trigger failed"); if (isToken) { vm.Nexus.UpgradeTokenContract(vm.RootStorage, contractName, script, abi); } else { vm.Chain.UpgradeContract(vm.Storage, contractName, script, abi); } vm.Notify(EventKind.ContractUpgrade, from, contractName); return(ExecutionState.Running); }
private static ExecutionState Runtime_DeployContract(RuntimeVM vm) { var tx = vm.Transaction; Throw.IfNull(tx, nameof(tx)); var pow = tx.Hash.GetDifficulty(); vm.Expect(pow >= (int)ProofOfWork.Minimal, "expected proof of work"); vm.ExpectStackSize(1); var from = vm.PopAddress(); vm.Expect(from.IsUser, "address must be user"); if (vm.Nexus.HasGenesis) { //Runtime.Expect(org != DomainSettings.ValidatorsOrganizationName, "cannot deploy contract via this organization"); vm.Expect(vm.IsStakeMaster(from), "needs to be master"); } vm.Expect(vm.IsWitness(from), "invalid witness"); var contractName = vm.PopString("contractName"); var contractAddress = SmartContract.GetAddressForName(contractName); var deployed = vm.Chain.IsContractDeployed(vm.Storage, contractAddress); // TODO if (vm.ProtocolVersion >= 2) { vm.Expect(!deployed, $"{contractName} is already deployed"); } else if (deployed) { return(ExecutionState.Running); } byte[] script; ContractInterface abi; bool isNative = Nexus.IsNativeContract(contractName); if (isNative) { if (contractName == "validator" && vm.GenesisAddress == Address.Null) { vm.Nexus.Initialize(from); } script = new byte[] { (byte)Opcode.RET }; var contractInstance = vm.Nexus.GetNativeContractByAddress(contractAddress); abi = contractInstance.ABI; } else { if (ValidationUtils.IsValidTicker(contractName)) { throw new VMException(vm, "use createToken instead for this kind of contract"); } else { vm.Expect(ValidationUtils.IsValidIdentifier(contractName), "invalid contract name"); } var isReserved = ValidationUtils.IsReservedIdentifier(contractName); if (isReserved && vm.IsWitness(vm.GenesisAddress)) { isReserved = false; } vm.Expect(!isReserved, $"name '{contractName}' reserved by system"); script = vm.PopBytes("contractScript"); var abiBytes = vm.PopBytes("contractABI"); abi = ContractInterface.FromBytes(abiBytes); var fuelCost = vm.GetGovernanceValue(Nexus.FuelPerContractDeployTag); // governance value is in usd fiat, here convert from fiat to fuel amount fuelCost = vm.GetTokenQuote(DomainSettings.FiatTokenSymbol, DomainSettings.FuelTokenSymbol, fuelCost); // burn the "cost" tokens vm.BurnTokens(DomainSettings.FuelTokenSymbol, from, fuelCost); } // ABI validation ValidateABI(vm, contractName, abi, isNative); var success = vm.Chain.DeployContractScript(vm.Storage, from, contractName, contractAddress, script, abi); vm.Expect(success, $"deployment of {contractName} failed"); var constructor = abi.FindMethod(SmartContract.ConstructorName); if (constructor != null) { vm.CallContext(contractName, constructor, from); } vm.Notify(EventKind.ContractDeploy, from, contractName); return(ExecutionState.Running); }