/// <summary> /// Applies an internally generated contract creation message to the current state. /// </summary> public StateTransitionResult Apply(IState state, InternalCreateMessage message) { bool enoughBalance = this.EnsureSenderHasEnoughBalance(state, message.From, message.Amount); if (!enoughBalance) { return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance)); } byte[] contractCode = state.ContractState.GetCode(message.From); uint160 address = state.GenerateAddress(this.AddressGenerator); // For internal creates we need to add the value contained in the contract invocation transaction // to the internal transfer list. This must occur before we apply the message to the state. // For external creates we do not need to do this. state.AddInternalTransfer(new TransferInfo { From = message.From, To = address, Value = message.Amount }); StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, address, message.Type); return(result); }
/// <summary> /// Applies an internally generated contract creation message to the current state. /// </summary> public StateTransitionResult Apply(InternalCreateMessage message) { bool enoughBalance = this.EnsureContractHasEnoughBalance(message.From, message.Amount); if (!enoughBalance) { throw new InsufficientBalanceException(); } byte[] contractCode = this.intermediateState.GetCode(message.From); StateTransitionResult result = this.ApplyCreate(message.Parameters, contractCode, message, message.Type); // For successful internal creates we need to add the transfer to the internal transfer list. // For external creates we do not need to do this. if (result.IsSuccess) { this.internalTransfers.Add(new TransferInfo { From = message.From, To = result.Success.ContractAddress, Value = message.Amount }); } return(result); }
/// <summary> /// Applies an internally generated contract creation message to the current state. /// </summary> public StateTransitionResult Apply(IState state, InternalCreateMessage message) { bool enoughBalance = this.EnsureSenderHasEnoughBalance(state, message.From, message.Amount); if (!enoughBalance) { return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance)); // Trivial - just return and let the MethodCall gas account for it. } var gasMeter = new GasMeter(message.GasLimit); gasMeter.Spend((Gas)GasPriceList.CreateCost); byte[] contractCode = state.ContractState.GetCode(message.From); uint160 address = state.GenerateAddress(this.AddressGenerator); // For internal creates we need to add the value contained in the contract invocation transaction // to the internal transfer list. This must occur before we apply the message to the state. // For external creates we do not need to do this. state.AddInternalTransfer(new TransferInfo(message.From, address, message.Amount)); StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, address, gasMeter, message.Type); return(result); }
/// <summary> /// Applies an internally generated contract creation message to the current state. /// </summary> public StateTransitionResult Apply(IState state, InternalCreateMessage message) { bool enoughBalance = this.EnsureContractHasEnoughBalance(state, message.From, message.Amount); if (!enoughBalance) { return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance)); } byte[] contractCode = state.ContractState.GetCode(message.From); StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, message.Type); // For successful internal creates we need to add the transfer to the internal transfer list. // For external creates we do not need to do this. if (result.IsSuccess) { state.AddInternalTransfer(new TransferInfo { From = message.From, To = result.Success.ContractAddress, Value = message.Amount }); } return(result); }
///<inheritdoc /> public ICreateResult Create <T>(ISmartContractState smartContractState, ulong amountToTransfer, object[] parameters, ulong gasLimit = 0) { Gas gasRemaining = smartContractState.GasMeter.GasAvailable; // For a method call, send all the gas unless an amount was selected.Should only call trusted methods so re - entrance is less problematic. ulong gasBudget = (gasLimit != 0) ? gasLimit : gasRemaining; Debug.WriteLine("Gas budget:" + gasBudget); if (gasRemaining < gasBudget || gasRemaining < GasPriceList.CreateCost) { return(CreateResult.Failed()); } var message = new InternalCreateMessage( smartContractState.Message.ContractAddress.ToUint160(), amountToTransfer, (Gas)gasBudget, parameters, typeof(T).Name ); // Create a snapshot of the current state IState newState = this.state.Snapshot(); // Apply the message to the snapshot StateTransitionResult result = this.stateProcessor.Apply(newState, message); // Transition the current state to the new state if (result.IsSuccess) { this.state.TransitionTo(newState); } smartContractState.GasMeter.Spend(result.GasConsumed); return(result.IsSuccess ? CreateResult.Succeeded(result.Success.ContractAddress.ToAddress()) : CreateResult.Failed()); }
///<inheritdoc /> public ICreateResult Create <T>(ISmartContractState smartContractState, ulong amountToTransfer, object[] parameters, ulong gasLimit = 0) { ulong gasBudget = (gasLimit != 0) ? gasLimit : smartContractState.GasMeter.GasAvailable; var message = new InternalCreateMessage( smartContractState.Message.ContractAddress.ToUint160(this.network), amountToTransfer, (Gas)gasBudget, parameters, typeof(T).Name ); var result = this.state.Apply(message); return(result.IsSuccess ? CreateResult.Succeeded(result.Success.ContractAddress.ToAddress(this.network)) : CreateResult.Failed()); }