/// <summary>
        /// Applies an externally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, ExternalCreateMessage message)
        {
            // We need to generate an address here so that we can set the initial balance.
            uint160 address = state.GenerateAddress(this.AddressGenerator);

            // For external creates we need to increment the balance state to take into
            // account any funds sent as part of the original contract invocation transaction.
            state.AddInitialTransfer(new TransferInfo {
                Value = message.Amount, To = address, From = message.From
            });

            return(this.ApplyCreate(state, message.Parameters, message.Code, message, address));
        }
Exemple #2
0
        /// <summary>
        /// Applies an externally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, ExternalCreateMessage message)
        {
            var gasMeter = new GasMeter(message.GasLimit);

            gasMeter.Spend((Gas)GasPriceList.CreateCost);

            // We need to generate an address here so that we can set the initial balance.
            uint160 address = state.GenerateAddress(this.AddressGenerator);

            // For external creates we need to increment the balance state to take into
            // account any funds sent as part of the original contract invocation transaction.
            state.AddInitialTransfer(new TransferInfo(message.From, address, message.Amount));

            return(this.ApplyCreate(state, message.Parameters, message.Code, message, address, gasMeter));
        }
Exemple #3
0
        public IContractExecutionResult Execute(IContractTransactionContext transactionContext)
        {
            // Deserialization can't fail because this has already been through SmartContractFormatRule.
            Result <ContractTxData> callDataDeserializationResult = this.serializer.Deserialize(transactionContext.Data);
            ContractTxData          callData = callDataDeserializationResult.Value;

            bool creation = callData.IsCreateContract;

            var block = new Block(
                transactionContext.BlockHeight,
                transactionContext.CoinbaseAddress.ToAddress(this.network)
                );

            IState state = this.stateFactory.Create(
                this.stateRoot,
                block,
                transactionContext.TxOutValue,
                transactionContext.TransactionHash);

            StateTransitionResult result;
            IState newState = state.Snapshot();

            if (creation)
            {
                var message = new ExternalCreateMessage(
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    callData.ContractExecutionCode,
                    callData.MethodParameters
                    );


                result = this.stateProcessor.Apply(newState, message);
            }
            else
            {
                var message = new ExternalCallMessage(
                    callData.ContractAddress,
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    new MethodCall(callData.MethodName, callData.MethodParameters)
                    );

                result = this.stateProcessor.Apply(newState, message);
            }

            if (result.IsSuccess)
            {
                state.TransitionTo(newState);
            }

            bool revert = !result.IsSuccess;

            Transaction internalTransaction = this.transferProcessor.Process(
                this.stateRoot,
                result.Success?.ContractAddress,
                transactionContext,
                state.InternalTransfers,
                revert);

            bool outOfGas = result.IsFailure && result.Error.Kind == StateTransitionErrorKind.OutOfGas;

            (Money fee, TxOut refundTxOut) = this.refundProcessor.Process(
                callData,
                transactionContext.MempoolFee,
                transactionContext.Sender,
                result.GasConsumed,
                outOfGas);

            var executionResult = new SmartContractExecutionResult
            {
                To = !callData.IsCreateContract ? callData.ContractAddress : null,
                NewContractAddress  = !revert && creation ? result.Success?.ContractAddress : null,
                ErrorMessage        = result.Error?.GetErrorMessage(),
                Revert              = revert,
                GasConsumed         = result.GasConsumed,
                Return              = result.Success?.ExecutionResult,
                InternalTransaction = internalTransaction,
                Fee    = fee,
                Refund = refundTxOut,
                Logs   = state.GetLogs(this.contractPrimitiveSerializer)
            };

            return(executionResult);
        }
Exemple #4
0
 /// <summary>
 /// Applies an externally generated contract creation message to the current state.
 /// </summary>
 public StateTransitionResult Apply(ExternalCreateMessage message)
 {
     return(this.ApplyCreate(message.Parameters, message.Code, message));
 }