From 64f0a31704e4f2b118b3ceea354f42110d27fc43 Mon Sep 17 00:00:00 2001 From: George Kudrayvtsev Date: Wed, 22 Mar 2023 16:31:16 -0700 Subject: [PATCH] Update test cases to build xdr w/ new value overhaul --- .../integration/invokehostfunction_test.go | 56 +- .../horizon/internal/integration/sac_test.go | 2122 ++++++++--------- 2 files changed, 1078 insertions(+), 1100 deletions(-) diff --git a/services/horizon/internal/integration/invokehostfunction_test.go b/services/horizon/internal/integration/invokehostfunction_test.go index 0846ca2e79..541a6f3d5d 100644 --- a/services/horizon/internal/integration/invokehostfunction_test.go +++ b/services/horizon/internal/integration/invokehostfunction_test.go @@ -201,13 +201,9 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { contractCodeLedgerKey := createContractOp.Footprint.ReadOnly[0] contractIdBytes := contractID[:] - contractIdParameterObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoBytes, - Bin: &contractIdBytes, - } contractIdParameter := xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &contractIdParameterObj, + Type: xdr.ScValTypeScvBytes, + Bytes: (*xdr.ScBytes)(&contractIdBytes), } contractFnParameterSym := xdr.ScSymbol("add") @@ -217,18 +213,7 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { } firstParamValue := xdr.Uint64(4) - firstParamValueObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoU64, - U64: &firstParamValue, - } - secondParamValue := xdr.Uint64(5) - secondParamValueObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoU64, - U64: &secondParamValue, - } - - contractCodeLedgerkeyAddr := xdr.ScStaticScsLedgerKeyContractCode invokeHostFunctionOp := &txnbuild.InvokeHostFunction{ Function: xdr.HostFunction{ @@ -237,12 +222,12 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { contractIdParameter, contractFnParameter, xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &firstParamValueObj, + Type: xdr.ScValTypeScvU64, + U64: &firstParamValue, }, xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &secondParamValueObj, + Type: xdr.ScValTypeScvU64, + U64: &secondParamValue, }, }, }, @@ -253,8 +238,8 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { ContractData: &xdr.LedgerKeyContractData{ ContractId: contractID, Key: xdr.ScVal{ - Type: xdr.ScValTypeScvStatic, - Ic: &contractCodeLedgerkeyAddr, + Type: xdr.ScValTypeScvLedgerKeyContractExecutable, + // symbolic: no value }, }, }, @@ -285,7 +270,7 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) { // check the function response, should have summed the two input numbers scval := invokeHostFunctionResult.MustSuccess() - assert.Equal(t, xdr.Uint64(9), scval.MustObj().MustU64()) + assert.Equal(t, xdr.Uint64(9), scval.MustU64()) } func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) { @@ -319,13 +304,9 @@ func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) { contractCodeLedgerKey := createContractOp.Footprint.ReadOnly[0] contractIdBytes := contractID[:] - contractIdParameterObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoBytes, - Bin: &contractIdBytes, - } contractIdParameter := xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &contractIdParameterObj, + Type: xdr.ScValTypeScvBytes, + Bytes: (*xdr.ScBytes)(&contractIdBytes), } contractFnParameterSym := xdr.ScSymbol("increment") @@ -335,8 +316,6 @@ func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) { } contractStateFootprintSym := xdr.ScSymbol("COUNTER") - contractCodeLedgerkeyAddr := xdr.ScStaticScsLedgerKeyContractCode - invokeHostFunctionOp := &txnbuild.InvokeHostFunction{ Function: xdr.HostFunction{ Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, @@ -352,8 +331,8 @@ func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) { ContractData: &xdr.LedgerKeyContractData{ ContractId: contractID, Key: xdr.ScVal{ - Type: xdr.ScValTypeScvStatic, - Ic: &contractCodeLedgerkeyAddr, + Type: xdr.ScValTypeScvLedgerKeyContractExecutable, + // symbolic: no value }, }, }, @@ -460,12 +439,11 @@ func assembleCreateContractOp(t *testing.T, sourceAccount string, wasmFileName s assert.NoError(t, err) contractHash := xdr.Hash(sha256.Sum256(installContractCodeArgs)) - ledgerKeyContractCodeAddr := xdr.ScStaticScsLedgerKeyContractCode ledgerKey := xdr.LedgerKeyContractData{ ContractId: xdr.Hash(hashedContractID), Key: xdr.ScVal{ - Type: xdr.ScValTypeScvStatic, - Ic: &ledgerKeyContractCodeAddr, + Type: xdr.ScValTypeScvLedgerKeyContractExecutable, + // symbolic: no value }, } @@ -477,8 +455,8 @@ func assembleCreateContractOp(t *testing.T, sourceAccount string, wasmFileName s Type: xdr.ContractIdTypeContractIdFromSourceAccount, Salt: &saltParameter, }, - Source: xdr.ScContractCode{ - Type: xdr.ScContractCodeTypeSccontractCodeWasmRef, + Source: xdr.ScContractExecutable{ + Type: xdr.ScContractExecutableTypeSccontractExecutableWasmRef, WasmId: &contractHash, }, }, diff --git a/services/horizon/internal/integration/sac_test.go b/services/horizon/internal/integration/sac_test.go index 39a963a564..f936875f16 100644 --- a/services/horizon/internal/integration/sac_test.go +++ b/services/horizon/internal/integration/sac_test.go @@ -1,1063 +1,1063 @@ package integration -import ( - "context" - "math" - "math/big" - "strings" - "testing" - - "github.com/stellar/go/amount" - "github.com/stellar/go/clients/horizonclient" - "github.com/stellar/go/keypair" - "github.com/stellar/go/protocols/stellarcore" - "github.com/stellar/go/services/horizon/internal/test/integration" - "github.com/stellar/go/strkey" - "github.com/stellar/go/txnbuild" - "github.com/stellar/go/xdr" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const sac_contract = "soroban_sac_test.wasm" - -// Tests use precompiled wasm bin files that are added to the testdata directory. -// Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile -// contract code if needed to new wasm. -// -// `test_add_u64.wasm` is compiled from ./serivces/horizon/internal/integration/contracts/sac_test -// - -func TestContractMintToAccount(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - recipientKp, recipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) - - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mint(itest, issuer, asset, "20", accountAddressParam(recipient.GetAccountID())), - ) - - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("20"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) - - otherRecipientKp, otherRecipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) - - // calling xfer from the issuer account will also mint the asset - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - xfer(itest, issuer, asset, "30", accountAddressParam(otherRecipient.GetAccountID())), - ) - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) - assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 2, - balanceAccounts: amount.MustParse("50"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractMintToContract(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - // Create recipient contract - recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", add_u64_contract) - - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mintWithAmt(itest, issuer, asset, i128Param(math.MaxInt64, math.MaxUint64-3), contractAddressParam(recipientContractID)), - ) - - balanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvObject, balanceAmount.Type) - assert.Equal(itest.CurrentTest(), xdr.ScObjectTypeScoI128, (*balanceAmount.Obj).Type) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64-3), (*balanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxInt64), (*balanceAmount.Obj).I128.Hi) - - // calling xfer from the issuer account will also mint the asset - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - xferWithAmount(itest, issuer, asset, i128Param(0, 3), contractAddressParam(recipientContractID)), - ) - - balanceAmount = assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64), (*balanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxInt64), (*balanceAmount.Obj).I128.Hi) - // balanceContracts = 2^127 - 1 - balanceContracts := new(big.Int).Lsh(big.NewInt(1), 127) - balanceContracts.Sub(balanceContracts, big.NewInt(1)) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 0, - balanceAccounts: 0, - numContracts: 1, - balanceContracts: balanceContracts, - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractTransferBetweenAccounts(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - recipientKp, recipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) - - itest.MustSubmitOperations( - itest.MasterAccount(), - itest.Master(), - &txnbuild.Payment{ - SourceAccount: issuer, - Destination: recipient.GetAccountID(), - Asset: txnbuild.CreditAsset{ - Code: code, - Issuer: issuer, - }, - Amount: "1000", - }, - ) - - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("1000"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) - - otherRecipientKp, otherRecipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) - - assertInvokeHostFnSucceeds( - itest, - recipientKp, - xfer(itest, recipientKp.Address(), asset, "30", accountAddressParam(otherRecipient.GetAccountID())), - ) - - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) - assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 2, - balanceAccounts: amount.MustParse("1000"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractTransferBetweenAccountAndContract(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USDLONG" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - recipientKp, recipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) - - itest.MustSubmitOperations( - itest.MasterAccount(), - itest.Master(), - &txnbuild.Payment{ - SourceAccount: issuer, - Destination: recipient.GetAccountID(), - Asset: txnbuild.CreditAsset{ - Code: code, - Issuer: issuer, - }, - Amount: "1000", - }, - ) - - // Create recipient contract - recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) - - // init recipient contract with the asset contract id - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - initAssetContract(itest, issuer, asset, recipientContractID), - ) - - // Add funds to recipient contract - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), - ) - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("1000"), - numContracts: 1, - balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), - contractID: stellarAssetContractID(itest, asset), - }) - - // transfer from account to contract - assertInvokeHostFnSucceeds( - itest, - recipientKp, - xfer(itest, recipientKp.Address(), asset, "30", contractAddressParam(recipientContractID)), - ) - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("970"), - numContracts: 1, - balanceContracts: big.NewInt(int64(amount.MustParse("1030"))), - contractID: stellarAssetContractID(itest, asset), - }) - - // transfer from contract to account - assertInvokeHostFnSucceeds( - itest, - recipientKp, - xferFromContract(itest, recipientKp.Address(), recipientContractID, "500", accountAddressParam(recipient.GetAccountID())), - ) - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1470")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("1470"), - numContracts: 1, - balanceContracts: big.NewInt(int64(amount.MustParse("530"))), - contractID: stellarAssetContractID(itest, asset), - }) - - balanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - assert.Equal(itest.CurrentTest(), xdr.Uint64(5300000000), (*balanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) -} - -func TestContractTransferBetweenContracts(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the token contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - // Create recipient contract - recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) - - // Create emitter contract - emitterContractID := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) - - // init emitter contract with the asset contract id - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - initAssetContract(itest, issuer, asset, emitterContractID), - ) - - // Add funds to emitter contract - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mint(itest, issuer, asset, "1000", contractAddressParam(emitterContractID)), - ) - - // Transfer funds from emitter to recipient - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - xferFromContract(itest, issuer, emitterContractID, "10", contractAddressParam(recipientContractID)), - ) - - // Check balances of emitter and recipient - emitterBalanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(emitterContractID)), - ) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*emitterBalanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*emitterBalanceAmount.Obj).I128.Hi) - - recipientBalanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(100000000), (*recipientBalanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*recipientBalanceAmount.Obj).I128.Hi) - - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 0, - balanceAccounts: 0, - numContracts: 2, - balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractBurnFromAccount(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - recipientKp, recipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) - - itest.MustSubmitOperations( - itest.MasterAccount(), - itest.Master(), - &txnbuild.Payment{ - SourceAccount: issuer, - Destination: recipient.GetAccountID(), - Asset: txnbuild.CreditAsset{ - Code: code, - Issuer: issuer, - }, - Amount: "1000", - }, - ) - - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("1000"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) - - assertInvokeHostFnSucceeds( - itest, - recipientKp, - burn(itest, recipientKp.Address(), asset, "500"), - ) - - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("500"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractBurnFromContract(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - // Create recipient contract - recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) - - // init contract with asset contract id - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - initAssetContract(itest, issuer, asset, recipientContractID), - ) - - // Add funds to recipient contract - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), - ) - - // Burn funds - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - burnSelf(itest, issuer, recipientContractID, "10"), - ) - - balanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 0, - balanceAccounts: 0, - numContracts: 1, - balanceContracts: big.NewInt(int64(amount.MustParse("990"))), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractClawbackFromAccount(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - // Give the master account the revocable flag (needed to set the clawback flag) - // and the clawback flag - setRevocableFlag := txnbuild.SetOptions{ - SetFlags: []txnbuild.AccountFlag{ - txnbuild.AuthRevocable, - txnbuild.AuthClawbackEnabled, - }, - } - itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - recipientKp, recipient := itest.CreateAccount("100") - itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) - - itest.MustSubmitOperations( - itest.MasterAccount(), - itest.Master(), - &txnbuild.Payment{ - SourceAccount: issuer, - Destination: recipient.GetAccountID(), - Asset: txnbuild.CreditAsset{ - Code: code, - Issuer: issuer, - }, - Amount: "1000", - }, - ) - - assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: amount.MustParse("1000"), - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) - - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - clawback(itest, issuer, asset, "1000", accountAddressParam(recipientKp.Address())), - ) - - assertContainsBalance(itest, recipientKp, issuer, code, 0) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 1, - balanceAccounts: 0, - numContracts: 0, - balanceContracts: big.NewInt(0), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func TestContractClawbackFromContract(t *testing.T) { - if integration.GetCoreMaxSupportedProtocol() < 20 { - t.Skip("This test run does not support less than Protocol 20") - } - - itest := integration.NewTest(t, integration.Config{ - ProtocolVersion: 20, - }) - - // Give the master account the revocable flag (needed to set the clawback flag) - // and the clawback flag - setRevocableFlag := txnbuild.SetOptions{ - SetFlags: []txnbuild.AccountFlag{ - txnbuild.AuthRevocable, - txnbuild.AuthClawbackEnabled, - }, - } - itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) - - issuer := itest.Master().Address() - code := "USD" - asset := xdr.MustNewCreditAsset(code, issuer) - - // Create the contract - assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) - - // Create recipient contract - recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) - - // Add funds to recipient contract - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), - ) - - // Clawback funds - assertInvokeHostFnSucceeds( - itest, - itest.Master(), - clawback(itest, issuer, asset, "10", contractAddressParam(recipientContractID)), - ) - - balanceAmount := assertInvokeHostFnSucceeds( - itest, - itest.Master(), - balance(itest, issuer, asset, contractAddressParam(recipientContractID)), - ) - - assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.Obj).I128.Lo) - assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) - assertAssetStats(itest, assetStats{ - code: code, - issuer: issuer, - numAccounts: 0, - balanceAccounts: 0, - numContracts: 1, - balanceContracts: big.NewInt(int64(amount.MustParse("990"))), - contractID: stellarAssetContractID(itest, asset), - }) -} - -func assertContainsBalance(itest *integration.Test, acct *keypair.Full, issuer, code string, amt xdr.Int64) { - accountResponse := itest.MustGetAccount(acct) - if issuer == "" && code == "" { - xlmBalance, err := accountResponse.GetNativeBalance() - assert.NoError(itest.CurrentTest(), err) - assert.Equal(itest.CurrentTest(), amt, amount.MustParse(xlmBalance)) - } else { - assetBalance := accountResponse.GetCreditBalance(code, issuer) - assert.Equal(itest.CurrentTest(), amt, amount.MustParse(assetBalance)) - } -} - -type assetStats struct { - code string - issuer string - numAccounts int32 - balanceAccounts xdr.Int64 - numContracts int32 - balanceContracts *big.Int - contractID [32]byte -} - -func assertAssetStats(itest *integration.Test, expected assetStats) { - assets, err := itest.Client().Assets(horizonclient.AssetRequest{ - ForAssetCode: expected.code, - ForAssetIssuer: expected.issuer, - Limit: 1, - }) - assert.NoError(itest.CurrentTest(), err) - - if expected.numContracts == 0 && expected.numAccounts == 0 && - expected.balanceContracts.Cmp(big.NewInt(0)) == 0 && expected.balanceAccounts == 0 { - assert.Empty(itest.CurrentTest(), assets) - return - } - - assert.Len(itest.CurrentTest(), assets.Embedded.Records, 1) - asset := assets.Embedded.Records[0] - assert.Equal(itest.CurrentTest(), expected.code, asset.Code) - assert.Equal(itest.CurrentTest(), expected.issuer, asset.Issuer) - assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.NumAccounts) - assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.Accounts.Authorized) - assert.Equal(itest.CurrentTest(), expected.balanceAccounts, amount.MustParse(asset.Amount)) - assert.Equal(itest.CurrentTest(), expected.numContracts, asset.NumContracts) - parts := strings.Split(asset.ContractsAmount, ".") - assert.Len(itest.CurrentTest(), parts, 2) - contractsAmount, ok := new(big.Int).SetString(parts[0]+parts[1], 10) - assert.True(itest.CurrentTest(), ok) - assert.Equal(itest.CurrentTest(), expected.balanceContracts.String(), contractsAmount.String()) - assert.Equal(itest.CurrentTest(), strkey.MustEncode(strkey.VersionByteContract, expected.contractID[:]), asset.ContractID) -} - -func functionNameParam(name string) xdr.ScVal { - contractFnParameterSym := xdr.ScSymbol(name) - return xdr.ScVal{ - Type: xdr.ScValTypeScvSymbol, - Sym: &contractFnParameterSym, - } -} - -func contractIDParam(contractID xdr.Hash) xdr.ScVal { - contractIdBytes := contractID[:] - contractIdParameterObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoBytes, - Bin: &contractIdBytes, - } - return xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &contractIdParameterObj, - } -} - -func accountAddressParam(accountID string) xdr.ScVal { - accountObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoAddress, - Address: &xdr.ScAddress{ - Type: xdr.ScAddressTypeScAddressTypeAccount, - AccountId: xdr.MustAddressPtr(accountID), - }, - } - return xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &accountObj, - } -} - -func contractAddressParam(contractID xdr.Hash) xdr.ScVal { - contractObj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoAddress, - Address: &xdr.ScAddress{ - Type: xdr.ScAddressTypeScAddressTypeContract, - ContractId: &contractID, - }, - } - return xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &contractObj, - } -} - -func i128Param(hi, lo uint64) xdr.ScVal { - i128Obj := &xdr.ScObject{ - Type: xdr.ScObjectTypeScoI128, - I128: &xdr.Int128Parts{ - Hi: xdr.Uint64(hi), - Lo: xdr.Uint64(lo), - }, - } - return xdr.ScVal{ - Type: xdr.ScValTypeScvObject, - Obj: &i128Obj, - } -} - -func createSAC(itest *integration.Test, sourceAccount string, asset xdr.Asset) *txnbuild.InvokeHostFunction { - return addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, - CreateContractArgs: &xdr.CreateContractArgs{ - ContractId: xdr.ContractId{ - Type: xdr.ContractIdTypeContractIdFromAsset, - Asset: &asset, - }, - Source: xdr.ScContractCode{ - Type: xdr.ScContractCodeTypeSccontractCodeToken, - }, - }, - }, - SourceAccount: sourceAccount, - }) -} - -func mint(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - return mintWithAmt(itest, sourceAccount, asset, i128Param(0, uint64(amount.MustParse(assetAmount))), recipient) -} - -func mintWithAmt(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - functionNameParam("mint"), - accountAddressParam(sourceAccount), - recipient, - assetAmount, - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "mint", - stellarAssetContractID(itest, asset), - xdr.ScVec{ - accountAddressParam(sourceAccount), - recipient, - assetAmount, - }) - - return invokeHostFn -} - -func initAssetContract(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID xdr.Hash) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(sacTestcontractID), - functionNameParam("init"), - contractIDParam(stellarAssetContractID(itest, asset)), - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "init", - sacTestcontractID, - xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - }) - - return invokeHostFn -} - -func clawback(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - functionNameParam("clawback"), - accountAddressParam(sourceAccount), - recipient, - i128Param(0, uint64(amount.MustParse(assetAmount))), - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "clawback", - stellarAssetContractID(itest, asset), - xdr.ScVec{ - accountAddressParam(sourceAccount), - recipient, - i128Param(0, uint64(amount.MustParse(assetAmount))), - }) - - return invokeHostFn -} - -func balance(itest *integration.Test, sourceAccount string, asset xdr.Asset, holder xdr.ScVal) *txnbuild.InvokeHostFunction { - return addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - functionNameParam("balance"), - holder, - }, - }, - SourceAccount: sourceAccount, - }) -} - -func xfer(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - return xferWithAmount( - itest, - sourceAccount, - asset, - i128Param(0, uint64(amount.MustParse(assetAmount))), - recipient, - ) -} - -func xferWithAmount(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - functionNameParam("xfer"), - accountAddressParam(sourceAccount), - recipient, - assetAmount, - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "xfer", - stellarAssetContractID(itest, asset), - xdr.ScVec{ - accountAddressParam(sourceAccount), - recipient, - assetAmount, - }) - - return invokeHostFn -} - -// Invokes burn_self from the sac_test contract (which just burns assets from itself) -func burnSelf(itest *integration.Test, sourceAccount string, sacTestcontractID xdr.Hash, assetAmount string) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(sacTestcontractID), - functionNameParam("burn_self"), - i128Param(0, uint64(amount.MustParse(assetAmount))), - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "burn_self", - sacTestcontractID, - xdr.ScVec{ - i128Param(0, uint64(amount.MustParse(assetAmount))), - }) - - return invokeHostFn -} - -func xferFromContract(itest *integration.Test, sourceAccount string, sacTestcontractID xdr.Hash, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(sacTestcontractID), - functionNameParam("xfer"), - recipient, - i128Param(0, uint64(amount.MustParse(assetAmount))), - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "xfer", - sacTestcontractID, - xdr.ScVec{ - recipient, - i128Param(0, uint64(amount.MustParse(assetAmount))), - }) - - return invokeHostFn -} - -func burn(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string) *txnbuild.InvokeHostFunction { - invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ - Function: xdr.HostFunction{ - Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, - InvokeArgs: &xdr.ScVec{ - contractIDParam(stellarAssetContractID(itest, asset)), - functionNameParam("burn"), - accountAddressParam(sourceAccount), - i128Param(0, uint64(amount.MustParse(assetAmount))), - }, - }, - SourceAccount: sourceAccount, - }) - - invokeHostFn.Auth = addAuthNextInvokerFlow( - "burn", - stellarAssetContractID(itest, asset), - xdr.ScVec{ - accountAddressParam(sourceAccount), - i128Param(0, uint64(amount.MustParse(assetAmount))), - }) - - return invokeHostFn -} - -func addFootprint(itest *integration.Test, invokeHostFn *txnbuild.InvokeHostFunction) *txnbuild.InvokeHostFunction { - opXDR, err := invokeHostFn.BuildXDR() - require.NoError(itest.CurrentTest(), err) - - invokeHostFunctionOp := opXDR.Body.MustInvokeHostFunctionOp() - - // clear footprint so we can verify preflight response - response, err := itest.CoreClient().Preflight( - context.Background(), - invokeHostFn.SourceAccount, - invokeHostFunctionOp, - ) - require.NoError(itest.CurrentTest(), err) - require.Equal(itest.CurrentTest(), stellarcore.PreflightStatusOk, response.Status, response.Detail) - err = xdr.SafeUnmarshalBase64(response.Footprint, &invokeHostFn.Footprint) - require.NoError(itest.CurrentTest(), err) - return invokeHostFn -} - -func assertInvokeHostFnSucceeds(itest *integration.Test, signer *keypair.Full, op *txnbuild.InvokeHostFunction) *xdr.ScVal { - acc := itest.MustGetAccount(signer) - tx, err := itest.SubmitOperations(&acc, signer, op) - require.NoError(itest.CurrentTest(), err) - - clientTx, err := itest.Client().TransactionDetail(tx.Hash) - require.NoError(itest.CurrentTest(), err) - - effects, err := itest.Client().Effects(horizonclient.EffectRequest{ - ForTransaction: tx.Hash, - }) - require.NoError(itest.CurrentTest(), err) - // Horizon currently does not support effects for smart contract invocations - require.Empty(itest.CurrentTest(), effects.Embedded.Records) - - assert.Equal(itest.CurrentTest(), tx.Hash, clientTx.Hash) - var txResult xdr.TransactionResult - err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) - require.NoError(itest.CurrentTest(), err) - - opResults, ok := txResult.OperationResults() - assert.True(itest.CurrentTest(), ok) - assert.Equal(itest.CurrentTest(), len(opResults), 1) - invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() - assert.True(itest.CurrentTest(), ok) - assert.Equal(itest.CurrentTest(), invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) - return invokeHostFunctionResult.Success -} - -func stellarAssetContractID(itest *integration.Test, asset xdr.Asset) xdr.Hash { - contractID, err := asset.ContractID(itest.GetPassPhrase()) - require.NoError(itest.CurrentTest(), err) - return contractID -} - -func addAuthNextInvokerFlow(fnName string, contractId xdr.Hash, args xdr.ScVec) []xdr.ContractAuth { - return []xdr.ContractAuth{ - { - RootInvocation: xdr.AuthorizedInvocation{ - ContractId: contractId, - FunctionName: xdr.ScSymbol(fnName), - Args: args, - SubInvocations: nil, - }, - SignatureArgs: nil, - }, - } -} - -func mustCreateAndInstallContract(itest *integration.Test, signer *keypair.Full, contractSalt string, wasmFileName string) xdr.Hash { - installContractOp := assembleInstallContractCodeOp(itest.CurrentTest(), itest.Master().Address(), wasmFileName) - assertInvokeHostFnSucceeds(itest, signer, installContractOp) - createContractOp := assembleCreateContractOp(itest.CurrentTest(), itest.Master().Address(), wasmFileName, contractSalt, itest.GetPassPhrase()) - assertInvokeHostFnSucceeds(itest, signer, createContractOp) - return createContractOp.Footprint.ReadWrite[0].MustContractData().ContractId -} +// import ( +// "context" +// "math" +// "math/big" +// "strings" +// "testing" + +// "github.com/stellar/go/amount" +// "github.com/stellar/go/clients/horizonclient" +// "github.com/stellar/go/keypair" +// "github.com/stellar/go/protocols/stellarcore" +// "github.com/stellar/go/services/horizon/internal/test/integration" +// "github.com/stellar/go/strkey" +// "github.com/stellar/go/txnbuild" +// "github.com/stellar/go/xdr" + +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +// ) + +// const sac_contract = "soroban_sac_test.wasm" + +// // Tests use precompiled wasm bin files that are added to the testdata directory. +// // Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile +// // contract code if needed to new wasm. +// // +// // `test_add_u64.wasm` is compiled from ./serivces/horizon/internal/integration/contracts/sac_test +// // + +// func TestContractMintToAccount(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// recipientKp, recipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mint(itest, issuer, asset, "20", accountAddressParam(recipient.GetAccountID())), +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("20"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// otherRecipientKp, otherRecipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) + +// // calling xfer from the issuer account will also mint the asset +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// xfer(itest, issuer, asset, "30", accountAddressParam(otherRecipient.GetAccountID())), +// ) +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20")) +// assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 2, +// balanceAccounts: amount.MustParse("50"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractMintToContract(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// // Create recipient contract +// recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", add_u64_contract) + +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mintWithAmt(itest, issuer, asset, i128Param(math.MaxInt64, math.MaxUint64-3), contractAddressParam(recipientContractID)), +// ) + +// balanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) +// assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvObject, balanceAmount.Type) +// assert.Equal(itest.CurrentTest(), xdr.ScObjectTypeScoI128, (*balanceAmount.Obj).Type) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64-3), (*balanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxInt64), (*balanceAmount.Obj).I128.Hi) + +// // calling xfer from the issuer account will also mint the asset +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// xferWithAmount(itest, issuer, asset, i128Param(0, 3), contractAddressParam(recipientContractID)), +// ) + +// balanceAmount = assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64), (*balanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxInt64), (*balanceAmount.Obj).I128.Hi) +// // balanceContracts = 2^127 - 1 +// balanceContracts := new(big.Int).Lsh(big.NewInt(1), 127) +// balanceContracts.Sub(balanceContracts, big.NewInt(1)) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 0, +// balanceAccounts: 0, +// numContracts: 1, +// balanceContracts: balanceContracts, +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractTransferBetweenAccounts(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// recipientKp, recipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + +// itest.MustSubmitOperations( +// itest.MasterAccount(), +// itest.Master(), +// &txnbuild.Payment{ +// SourceAccount: issuer, +// Destination: recipient.GetAccountID(), +// Asset: txnbuild.CreditAsset{ +// Code: code, +// Issuer: issuer, +// }, +// Amount: "1000", +// }, +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("1000"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// otherRecipientKp, otherRecipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset)) + +// assertInvokeHostFnSucceeds( +// itest, +// recipientKp, +// xfer(itest, recipientKp.Address(), asset, "30", accountAddressParam(otherRecipient.GetAccountID())), +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) +// assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 2, +// balanceAccounts: amount.MustParse("1000"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractTransferBetweenAccountAndContract(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USDLONG" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// recipientKp, recipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + +// itest.MustSubmitOperations( +// itest.MasterAccount(), +// itest.Master(), +// &txnbuild.Payment{ +// SourceAccount: issuer, +// Destination: recipient.GetAccountID(), +// Asset: txnbuild.CreditAsset{ +// Code: code, +// Issuer: issuer, +// }, +// Amount: "1000", +// }, +// ) + +// // Create recipient contract +// recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + +// // init recipient contract with the asset contract id +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// initAssetContract(itest, issuer, asset, recipientContractID), +// ) + +// // Add funds to recipient contract +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), +// ) +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("1000"), +// numContracts: 1, +// balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// // transfer from account to contract +// assertInvokeHostFnSucceeds( +// itest, +// recipientKp, +// xfer(itest, recipientKp.Address(), asset, "30", contractAddressParam(recipientContractID)), +// ) +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("970"), +// numContracts: 1, +// balanceContracts: big.NewInt(int64(amount.MustParse("1030"))), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// // transfer from contract to account +// assertInvokeHostFnSucceeds( +// itest, +// recipientKp, +// xferFromContract(itest, recipientKp.Address(), recipientContractID, "500", accountAddressParam(recipient.GetAccountID())), +// ) +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1470")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("1470"), +// numContracts: 1, +// balanceContracts: big.NewInt(int64(amount.MustParse("530"))), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// balanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(5300000000), (*balanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) +// } + +// func TestContractTransferBetweenContracts(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the token contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// // Create recipient contract +// recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + +// // Create emitter contract +// emitterContractID := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) + +// // init emitter contract with the asset contract id +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// initAssetContract(itest, issuer, asset, emitterContractID), +// ) + +// // Add funds to emitter contract +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mint(itest, issuer, asset, "1000", contractAddressParam(emitterContractID)), +// ) + +// // Transfer funds from emitter to recipient +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// xferFromContract(itest, issuer, emitterContractID, "10", contractAddressParam(recipientContractID)), +// ) + +// // Check balances of emitter and recipient +// emitterBalanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(emitterContractID)), +// ) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*emitterBalanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*emitterBalanceAmount.Obj).I128.Hi) + +// recipientBalanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(100000000), (*recipientBalanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*recipientBalanceAmount.Obj).I128.Hi) + +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 0, +// balanceAccounts: 0, +// numContracts: 2, +// balanceContracts: big.NewInt(int64(amount.MustParse("1000"))), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractBurnFromAccount(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// recipientKp, recipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + +// itest.MustSubmitOperations( +// itest.MasterAccount(), +// itest.Master(), +// &txnbuild.Payment{ +// SourceAccount: issuer, +// Destination: recipient.GetAccountID(), +// Asset: txnbuild.CreditAsset{ +// Code: code, +// Issuer: issuer, +// }, +// Amount: "1000", +// }, +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("1000"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// assertInvokeHostFnSucceeds( +// itest, +// recipientKp, +// burn(itest, recipientKp.Address(), asset, "500"), +// ) + +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("500"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractBurnFromContract(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// // Create recipient contract +// recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a1", sac_contract) + +// // init contract with asset contract id +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// initAssetContract(itest, issuer, asset, recipientContractID), +// ) + +// // Add funds to recipient contract +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), +// ) + +// // Burn funds +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// burnSelf(itest, issuer, recipientContractID, "10"), +// ) + +// balanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 0, +// balanceAccounts: 0, +// numContracts: 1, +// balanceContracts: big.NewInt(int64(amount.MustParse("990"))), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractClawbackFromAccount(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// // Give the master account the revocable flag (needed to set the clawback flag) +// // and the clawback flag +// setRevocableFlag := txnbuild.SetOptions{ +// SetFlags: []txnbuild.AccountFlag{ +// txnbuild.AuthRevocable, +// txnbuild.AuthClawbackEnabled, +// }, +// } +// itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// recipientKp, recipient := itest.CreateAccount("100") +// itest.MustEstablishTrustline(recipientKp, recipient, txnbuild.MustAssetFromXDR(asset)) + +// itest.MustSubmitOperations( +// itest.MasterAccount(), +// itest.Master(), +// &txnbuild.Payment{ +// SourceAccount: issuer, +// Destination: recipient.GetAccountID(), +// Asset: txnbuild.CreditAsset{ +// Code: code, +// Issuer: issuer, +// }, +// Amount: "1000", +// }, +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000")) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: amount.MustParse("1000"), +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) + +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// clawback(itest, issuer, asset, "1000", accountAddressParam(recipientKp.Address())), +// ) + +// assertContainsBalance(itest, recipientKp, issuer, code, 0) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 1, +// balanceAccounts: 0, +// numContracts: 0, +// balanceContracts: big.NewInt(0), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func TestContractClawbackFromContract(t *testing.T) { +// if integration.GetCoreMaxSupportedProtocol() < 20 { +// t.Skip("This test run does not support less than Protocol 20") +// } + +// itest := integration.NewTest(t, integration.Config{ +// ProtocolVersion: 20, +// }) + +// // Give the master account the revocable flag (needed to set the clawback flag) +// // and the clawback flag +// setRevocableFlag := txnbuild.SetOptions{ +// SetFlags: []txnbuild.AccountFlag{ +// txnbuild.AuthRevocable, +// txnbuild.AuthClawbackEnabled, +// }, +// } +// itest.MustSubmitOperations(itest.MasterAccount(), itest.Master(), &setRevocableFlag) + +// issuer := itest.Master().Address() +// code := "USD" +// asset := xdr.MustNewCreditAsset(code, issuer) + +// // Create the contract +// assertInvokeHostFnSucceeds(itest, itest.Master(), createSAC(itest, issuer, asset)) + +// // Create recipient contract +// recipientContractID := mustCreateAndInstallContract(itest, itest.Master(), "a2", sac_contract) + +// // Add funds to recipient contract +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)), +// ) + +// // Clawback funds +// assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// clawback(itest, issuer, asset, "10", contractAddressParam(recipientContractID)), +// ) + +// balanceAmount := assertInvokeHostFnSucceeds( +// itest, +// itest.Master(), +// balance(itest, issuer, asset, contractAddressParam(recipientContractID)), +// ) + +// assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.Obj).I128.Lo) +// assert.Equal(itest.CurrentTest(), xdr.Uint64(0), (*balanceAmount.Obj).I128.Hi) +// assertAssetStats(itest, assetStats{ +// code: code, +// issuer: issuer, +// numAccounts: 0, +// balanceAccounts: 0, +// numContracts: 1, +// balanceContracts: big.NewInt(int64(amount.MustParse("990"))), +// contractID: stellarAssetContractID(itest, asset), +// }) +// } + +// func assertContainsBalance(itest *integration.Test, acct *keypair.Full, issuer, code string, amt xdr.Int64) { +// accountResponse := itest.MustGetAccount(acct) +// if issuer == "" && code == "" { +// xlmBalance, err := accountResponse.GetNativeBalance() +// assert.NoError(itest.CurrentTest(), err) +// assert.Equal(itest.CurrentTest(), amt, amount.MustParse(xlmBalance)) +// } else { +// assetBalance := accountResponse.GetCreditBalance(code, issuer) +// assert.Equal(itest.CurrentTest(), amt, amount.MustParse(assetBalance)) +// } +// } + +// type assetStats struct { +// code string +// issuer string +// numAccounts int32 +// balanceAccounts xdr.Int64 +// numContracts int32 +// balanceContracts *big.Int +// contractID [32]byte +// } + +// func assertAssetStats(itest *integration.Test, expected assetStats) { +// assets, err := itest.Client().Assets(horizonclient.AssetRequest{ +// ForAssetCode: expected.code, +// ForAssetIssuer: expected.issuer, +// Limit: 1, +// }) +// assert.NoError(itest.CurrentTest(), err) + +// if expected.numContracts == 0 && expected.numAccounts == 0 && +// expected.balanceContracts.Cmp(big.NewInt(0)) == 0 && expected.balanceAccounts == 0 { +// assert.Empty(itest.CurrentTest(), assets) +// return +// } + +// assert.Len(itest.CurrentTest(), assets.Embedded.Records, 1) +// asset := assets.Embedded.Records[0] +// assert.Equal(itest.CurrentTest(), expected.code, asset.Code) +// assert.Equal(itest.CurrentTest(), expected.issuer, asset.Issuer) +// assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.NumAccounts) +// assert.Equal(itest.CurrentTest(), expected.numAccounts, asset.Accounts.Authorized) +// assert.Equal(itest.CurrentTest(), expected.balanceAccounts, amount.MustParse(asset.Amount)) +// assert.Equal(itest.CurrentTest(), expected.numContracts, asset.NumContracts) +// parts := strings.Split(asset.ContractsAmount, ".") +// assert.Len(itest.CurrentTest(), parts, 2) +// contractsAmount, ok := new(big.Int).SetString(parts[0]+parts[1], 10) +// assert.True(itest.CurrentTest(), ok) +// assert.Equal(itest.CurrentTest(), expected.balanceContracts.String(), contractsAmount.String()) +// assert.Equal(itest.CurrentTest(), strkey.MustEncode(strkey.VersionByteContract, expected.contractID[:]), asset.ContractID) +// } + +// func functionNameParam(name string) xdr.ScVal { +// contractFnParameterSym := xdr.ScSymbol(name) +// return xdr.ScVal{ +// Type: xdr.ScValTypeScvSymbol, +// Sym: &contractFnParameterSym, +// } +// } + +// func contractIDParam(contractID xdr.Hash) xdr.ScVal { +// contractIdBytes := contractID[:] +// contractIdParameterObj := &xdr.ScObject{ +// Type: xdr.ScObjectTypeScoBytes, +// Bin: &contractIdBytes, +// } +// return xdr.ScVal{ +// Type: xdr.ScValTypeScvObject, +// Obj: &contractIdParameterObj, +// } +// } + +// func accountAddressParam(accountID string) xdr.ScVal { +// accountObj := &xdr.ScObject{ +// Type: xdr.ScObjectTypeScoAddress, +// Address: &xdr.ScAddress{ +// Type: xdr.ScAddressTypeScAddressTypeAccount, +// AccountId: xdr.MustAddressPtr(accountID), +// }, +// } +// return xdr.ScVal{ +// Type: xdr.ScValTypeScvObject, +// Obj: &accountObj, +// } +// } + +// func contractAddressParam(contractID xdr.Hash) xdr.ScVal { +// contractObj := &xdr.ScObject{ +// Type: xdr.ScObjectTypeScoAddress, +// Address: &xdr.ScAddress{ +// Type: xdr.ScAddressTypeScAddressTypeContract, +// ContractId: &contractID, +// }, +// } +// return xdr.ScVal{ +// Type: xdr.ScValTypeScvObject, +// Obj: &contractObj, +// } +// } + +// func i128Param(hi, lo uint64) xdr.ScVal { +// i128Obj := &xdr.ScObject{ +// Type: xdr.ScObjectTypeScoI128, +// I128: &xdr.Int128Parts{ +// Hi: xdr.Uint64(hi), +// Lo: xdr.Uint64(lo), +// }, +// } +// return xdr.ScVal{ +// Type: xdr.ScValTypeScvObject, +// Obj: &i128Obj, +// } +// } + +// func createSAC(itest *integration.Test, sourceAccount string, asset xdr.Asset) *txnbuild.InvokeHostFunction { +// return addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract, +// CreateContractArgs: &xdr.CreateContractArgs{ +// ContractId: xdr.ContractId{ +// Type: xdr.ContractIdTypeContractIdFromAsset, +// Asset: &asset, +// }, +// Source: xdr.ScContractCode{ +// Type: xdr.ScContractCodeTypeSccontractCodeToken, +// }, +// }, +// }, +// SourceAccount: sourceAccount, +// }) +// } + +// func mint(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// return mintWithAmt(itest, sourceAccount, asset, i128Param(0, uint64(amount.MustParse(assetAmount))), recipient) +// } + +// func mintWithAmt(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// functionNameParam("mint"), +// accountAddressParam(sourceAccount), +// recipient, +// assetAmount, +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "mint", +// stellarAssetContractID(itest, asset), +// xdr.ScVec{ +// accountAddressParam(sourceAccount), +// recipient, +// assetAmount, +// }) + +// return invokeHostFn +// } + +// func initAssetContract(itest *integration.Test, sourceAccount string, asset xdr.Asset, sacTestcontractID xdr.Hash) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(sacTestcontractID), +// functionNameParam("init"), +// contractIDParam(stellarAssetContractID(itest, asset)), +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "init", +// sacTestcontractID, +// xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// }) + +// return invokeHostFn +// } + +// func clawback(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// functionNameParam("clawback"), +// accountAddressParam(sourceAccount), +// recipient, +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "clawback", +// stellarAssetContractID(itest, asset), +// xdr.ScVec{ +// accountAddressParam(sourceAccount), +// recipient, +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }) + +// return invokeHostFn +// } + +// func balance(itest *integration.Test, sourceAccount string, asset xdr.Asset, holder xdr.ScVal) *txnbuild.InvokeHostFunction { +// return addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// functionNameParam("balance"), +// holder, +// }, +// }, +// SourceAccount: sourceAccount, +// }) +// } + +// func xfer(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// return xferWithAmount( +// itest, +// sourceAccount, +// asset, +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// recipient, +// ) +// } + +// func xferWithAmount(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount xdr.ScVal, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// functionNameParam("xfer"), +// accountAddressParam(sourceAccount), +// recipient, +// assetAmount, +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "xfer", +// stellarAssetContractID(itest, asset), +// xdr.ScVec{ +// accountAddressParam(sourceAccount), +// recipient, +// assetAmount, +// }) + +// return invokeHostFn +// } + +// // Invokes burn_self from the sac_test contract (which just burns assets from itself) +// func burnSelf(itest *integration.Test, sourceAccount string, sacTestcontractID xdr.Hash, assetAmount string) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(sacTestcontractID), +// functionNameParam("burn_self"), +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "burn_self", +// sacTestcontractID, +// xdr.ScVec{ +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }) + +// return invokeHostFn +// } + +// func xferFromContract(itest *integration.Test, sourceAccount string, sacTestcontractID xdr.Hash, assetAmount string, recipient xdr.ScVal) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(sacTestcontractID), +// functionNameParam("xfer"), +// recipient, +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "xfer", +// sacTestcontractID, +// xdr.ScVec{ +// recipient, +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }) + +// return invokeHostFn +// } + +// func burn(itest *integration.Test, sourceAccount string, asset xdr.Asset, assetAmount string) *txnbuild.InvokeHostFunction { +// invokeHostFn := addFootprint(itest, &txnbuild.InvokeHostFunction{ +// Function: xdr.HostFunction{ +// Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract, +// InvokeArgs: &xdr.ScVec{ +// contractIDParam(stellarAssetContractID(itest, asset)), +// functionNameParam("burn"), +// accountAddressParam(sourceAccount), +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }, +// }, +// SourceAccount: sourceAccount, +// }) + +// invokeHostFn.Auth = addAuthNextInvokerFlow( +// "burn", +// stellarAssetContractID(itest, asset), +// xdr.ScVec{ +// accountAddressParam(sourceAccount), +// i128Param(0, uint64(amount.MustParse(assetAmount))), +// }) + +// return invokeHostFn +// } + +// func addFootprint(itest *integration.Test, invokeHostFn *txnbuild.InvokeHostFunction) *txnbuild.InvokeHostFunction { +// opXDR, err := invokeHostFn.BuildXDR() +// require.NoError(itest.CurrentTest(), err) + +// invokeHostFunctionOp := opXDR.Body.MustInvokeHostFunctionOp() + +// // clear footprint so we can verify preflight response +// response, err := itest.CoreClient().Preflight( +// context.Background(), +// invokeHostFn.SourceAccount, +// invokeHostFunctionOp, +// ) +// require.NoError(itest.CurrentTest(), err) +// require.Equal(itest.CurrentTest(), stellarcore.PreflightStatusOk, response.Status, response.Detail) +// err = xdr.SafeUnmarshalBase64(response.Footprint, &invokeHostFn.Footprint) +// require.NoError(itest.CurrentTest(), err) +// return invokeHostFn +// } + +// func assertInvokeHostFnSucceeds(itest *integration.Test, signer *keypair.Full, op *txnbuild.InvokeHostFunction) *xdr.ScVal { +// acc := itest.MustGetAccount(signer) +// tx, err := itest.SubmitOperations(&acc, signer, op) +// require.NoError(itest.CurrentTest(), err) + +// clientTx, err := itest.Client().TransactionDetail(tx.Hash) +// require.NoError(itest.CurrentTest(), err) + +// effects, err := itest.Client().Effects(horizonclient.EffectRequest{ +// ForTransaction: tx.Hash, +// }) +// require.NoError(itest.CurrentTest(), err) +// // Horizon currently does not support effects for smart contract invocations +// require.Empty(itest.CurrentTest(), effects.Embedded.Records) + +// assert.Equal(itest.CurrentTest(), tx.Hash, clientTx.Hash) +// var txResult xdr.TransactionResult +// err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult) +// require.NoError(itest.CurrentTest(), err) + +// opResults, ok := txResult.OperationResults() +// assert.True(itest.CurrentTest(), ok) +// assert.Equal(itest.CurrentTest(), len(opResults), 1) +// invokeHostFunctionResult, ok := opResults[0].MustTr().GetInvokeHostFunctionResult() +// assert.True(itest.CurrentTest(), ok) +// assert.Equal(itest.CurrentTest(), invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess) +// return invokeHostFunctionResult.Success +// } + +// func stellarAssetContractID(itest *integration.Test, asset xdr.Asset) xdr.Hash { +// contractID, err := asset.ContractID(itest.GetPassPhrase()) +// require.NoError(itest.CurrentTest(), err) +// return contractID +// } + +// func addAuthNextInvokerFlow(fnName string, contractId xdr.Hash, args xdr.ScVec) []xdr.ContractAuth { +// return []xdr.ContractAuth{ +// { +// RootInvocation: xdr.AuthorizedInvocation{ +// ContractId: contractId, +// FunctionName: xdr.ScSymbol(fnName), +// Args: args, +// SubInvocations: nil, +// }, +// SignatureArgs: nil, +// }, +// } +// } + +// func mustCreateAndInstallContract(itest *integration.Test, signer *keypair.Full, contractSalt string, wasmFileName string) xdr.Hash { +// installContractOp := assembleInstallContractCodeOp(itest.CurrentTest(), itest.Master().Address(), wasmFileName) +// assertInvokeHostFnSucceeds(itest, signer, installContractOp) +// createContractOp := assembleCreateContractOp(itest.CurrentTest(), itest.Master().Address(), wasmFileName, contractSalt, itest.GetPassPhrase()) +// assertInvokeHostFnSucceeds(itest, signer, createContractOp) +// return createContractOp.Footprint.ReadWrite[0].MustContractData().ContractId +// }