diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go index 9afd5ae1..e4c087fc 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/contract.go @@ -15,18 +15,28 @@ import ( var testSalt = sha256.Sum256([]byte("a1")) -func GetHelloWorldContract() []byte { - contractFile := path.Join(GetCurrentDirectory(), "../../../../../wasms/test_hello_world.wasm") +func getTestContract(name string) []byte { + contractFile := path.Join(GetCurrentDirectory(), "../../../../../wasms/test_"+name+".wasm") ret, err := os.ReadFile(contractFile) if err != nil { str := fmt.Sprintf( - "unable to read test_hello_world.wasm (%v) please run `make build-test-wasms` at the project root directory", - err) + "unable to read %s.wasm (%v) please run `make build-test-wasms` at the project root directory", + name, + err, + ) panic(str) } return ret } +func GetHelloWorldContract() []byte { + return getTestContract("hello_world") +} + +func GetNoArgConstructorContract() []byte { + return getTestContract("no_arg_constructor") +} + func CreateInvokeHostOperation(sourceAccount string, contractID xdr.Hash, method string, args ...xdr.ScVal) *txnbuild.InvokeHostFunction { return &txnbuild.InvokeHostFunction{ HostFunction: xdr.HostFunction{ @@ -116,3 +126,39 @@ func createCreateContractOperation(sourceAccount string, salt xdr.Uint256, contr SourceAccount: sourceAccount, } } + +func CreateCreateNoArgConstructorContractOperation(sourceAccount string) *txnbuild.InvokeHostFunction { + contractHash := xdr.Hash(sha256.Sum256(GetNoArgConstructorContract())) + salt := xdr.Uint256(testSalt) + return createCreateContractV2Operation(sourceAccount, salt, contractHash) +} + +func createCreateContractV2Operation( + sourceAccount string, salt xdr.Uint256, contractHash xdr.Hash, +) *txnbuild.InvokeHostFunction { + sourceAccountID := xdr.MustAddress(sourceAccount) + return &txnbuild.InvokeHostFunction{ + HostFunction: xdr.HostFunction{ + Type: xdr.HostFunctionTypeHostFunctionTypeCreateContractV2, + CreateContractV2: &xdr.CreateContractArgsV2{ + ContractIdPreimage: xdr.ContractIdPreimage{ + Type: xdr.ContractIdPreimageTypeContractIdPreimageFromAddress, + FromAddress: &xdr.ContractIdPreimageFromAddress{ + Address: xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeAccount, + AccountId: &sourceAccountID, + }, + Salt: salt, + }, + }, + Executable: xdr.ContractExecutable{ + Type: xdr.ContractExecutableTypeContractExecutableWasm, + WasmHash: &contractHash, + }, + ConstructorArgs: nil, + }, + }, + Auth: []xdr.SorobanAuthorizationEntry{}, + SourceAccount: sourceAccount, + } +} diff --git a/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go b/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go index a800bd0e..a8c4aa58 100644 --- a/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go +++ b/cmd/soroban-rpc/internal/integrationtest/infrastructure/test.go @@ -652,6 +652,11 @@ func (i *Test) UploadHelloWorldContract() (methods.GetTransactionResponse, xdr.H return i.uploadContract(contractBinary) } +func (i *Test) UploadNoArgConstructorContract() (methods.GetTransactionResponse, xdr.Hash) { + contractBinary := GetNoArgConstructorContract() + return i.uploadContract(contractBinary) +} + func (i *Test) uploadContract(contractBinary []byte) (methods.GetTransactionResponse, xdr.Hash) { contractHash := xdr.Hash(sha256.Sum256(contractBinary)) op := CreateUploadWasmOperation(i.MasterAccount().GetAccountID(), contractBinary) diff --git a/cmd/soroban-rpc/internal/integrationtest/transaction_test.go b/cmd/soroban-rpc/internal/integrationtest/transaction_test.go index 7dc0be0e..1dfd1f4e 100644 --- a/cmd/soroban-rpc/internal/integrationtest/transaction_test.go +++ b/cmd/soroban-rpc/internal/integrationtest/transaction_test.go @@ -202,3 +202,25 @@ func TestSendTransactionFailedInvalidXDR(t *testing.T) { require.Equal(t, "invalid_xdr", jsonRPCErr.Message) require.Equal(t, jrpc2.InvalidParams, jsonRPCErr.Code) } + +func TestContractCreationWithConstructor(t *testing.T) { + if infrastructure.GetCoreMaxSupportedProtocol() < 22 { + t.Skip("Only test this for protocol >= 22") + } + test := infrastructure.NewTest(t, nil) + + test.UploadNoArgConstructorContract() + + client := test.GetRPCLient() + + params := infrastructure.PreflightTransactionParams(t, client, + infrastructure.CreateTransactionParams( + test.MasterAccount(), + infrastructure.CreateCreateNoArgConstructorContractOperation(test.MasterAccount().GetAccountID()), + ), + ) + + tx, err := txnbuild.NewTransaction(params) + require.NoError(t, err) + infrastructure.SendSuccessfulTransaction(t, client, test.MasterKey(), tx) +} diff --git a/wasms/test_no_arg_constructor.wasm b/wasms/test_no_arg_constructor.wasm new file mode 100644 index 00000000..14c0295d Binary files /dev/null and b/wasms/test_no_arg_constructor.wasm differ