Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 44 additions & 6 deletions test/integration/uexecutor/inbound_cea_gas_and_payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,12 +464,43 @@ func TestInboundCEAGasAndPayload(t *testing.T) {
"UEA should have received tokens via GAS_AND_PAYLOAD CEA deposit")
})

t.Run("verified payload hash stores UEA owner as sender when isCEA is true for GAS_AND_PAYLOAD", func(t *testing.T) {
t.Run("verified payload hash stored under UEA origin chain with UEA owner as sender for CEA GAS_AND_PAYLOAD", func(t *testing.T) {
chainApp, ctx, vals, _, coreVals, ueaAddrHex := setupInboundCEAGasAndPayloadTest(t, 4)
usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr
prc20Address := utils.GetDefaultAddresses().PRC20USDCAddr
testAddress := utils.GetDefaultAddresses().DefaultTestAddr

// person B — a different sender that is NOT the UEA owner
// Register a second chain (eip155:97) so we can send a CEA inbound from a different chain
chainApp.UregistryKeeper.AddChainConfig(ctx, &uregistrytypes.ChainConfig{
Chain: "eip155:97",
VmType: uregistrytypes.VmType_EVM,
PublicRpcUrl: "https://data-seed-prebsc-1-s1.binance.org:8545",
GatewayAddress: "0x0000000000000000000000000000000000000000",
BlockConfirmation: &uregistrytypes.BlockConfirmation{
FastInbound: 5,
StandardInbound: 12,
},
Enabled: &uregistrytypes.ChainEnabled{
IsInboundEnabled: true,
IsOutboundEnabled: true,
},
})
chainApp.UregistryKeeper.AddTokenConfig(ctx, &uregistrytypes.TokenConfig{
Chain: "eip155:97",
Address: usdcAddress.String(),
Name: "USD Coin",
Symbol: "USDC",
Decimals: 6,
Enabled: true,
LiquidityCap: "1000000000000000000000000",
TokenType: 1,
NativeRepresentation: &uregistrytypes.NativeRepresentation{
Denom: "",
ContractAddress: prc20Address.String(),
},
})

// person B — a different sender on a different chain
personBSender := utils.GetDefaultAddresses().TargetAddr2

validUP := &uexecutortypes.UniversalPayload{
Expand All @@ -484,8 +515,9 @@ func TestInboundCEAGasAndPayload(t *testing.T) {
VType: uexecutortypes.VerificationType(1),
}

// CEA inbound from eip155:97, but UEA origin is eip155:11155111
ceaInbound := &uexecutortypes.Inbound{
SourceChain: "eip155:11155111",
SourceChain: "eip155:97",
TxHash: "0xceagas07",
Sender: personBSender,
Recipient: ueaAddrHex.String(),
Expand All @@ -510,12 +542,18 @@ func TestInboundCEAGasAndPayload(t *testing.T) {
require.NoError(t, err)
}

// Verify the stored sender in VerifiedTxMetadata is the UEA owner, not personBSender
verified, found, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ceaInbound.SourceChain, ceaInbound.TxHash)
// Payload hash should be stored under UEA origin chain (eip155:11155111), NOT source chain (eip155:97)
ueaOriginChain := "eip155:11155111"
verified, found, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ueaOriginChain, ceaInbound.TxHash)
require.NoError(t, err)
require.True(t, found, "verified tx metadata should exist after execution")
require.True(t, found, "verified tx metadata should be stored under UEA origin chain")
require.NotEmpty(t, verified.PayloadHashes, "payload hashes should be stored")

// Should NOT be found under source chain
_, foundUnderSource, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ceaInbound.SourceChain, ceaInbound.TxHash)
require.NoError(t, err)
require.False(t, foundUnderSource, "verified tx metadata should NOT be stored under inbound source chain for CEA")

// The sender should be the UEA owner (testAddress), NOT personBSender
require.NotEqual(t, personBSender, verified.Sender,
"stored sender should NOT be the CEA executor")
Expand Down
50 changes: 44 additions & 6 deletions test/integration/uexecutor/inbound_cea_payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,12 +693,43 @@ func TestInboundCEAFundsAndPayload(t *testing.T) {
"isCEA=true should succeed using recipient UEA directly, ignoring whether sender has a UEA")
})

t.Run("verified payload hash stores UEA owner as sender when isCEA is true for FUNDS_AND_PAYLOAD", func(t *testing.T) {
t.Run("verified payload hash stored under UEA origin chain with UEA owner as sender for CEA FUNDS_AND_PAYLOAD", func(t *testing.T) {
chainApp, ctx, vals, _, coreVals, ueaAddrHex := setupInboundCEAPayloadTest(t, 4)
usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr
prc20Address := utils.GetDefaultAddresses().PRC20USDCAddr
testAddress := utils.GetDefaultAddresses().DefaultTestAddr

// person B — a different sender that is NOT the UEA owner
// Register a second chain (eip155:97) so we can send a CEA inbound from a different chain
chainApp.UregistryKeeper.AddChainConfig(ctx, &uregistrytypes.ChainConfig{
Chain: "eip155:97",
VmType: uregistrytypes.VmType_EVM,
PublicRpcUrl: "https://data-seed-prebsc-1-s1.binance.org:8545",
GatewayAddress: "0x0000000000000000000000000000000000000000",
BlockConfirmation: &uregistrytypes.BlockConfirmation{
FastInbound: 5,
StandardInbound: 12,
},
Enabled: &uregistrytypes.ChainEnabled{
IsInboundEnabled: true,
IsOutboundEnabled: true,
},
})
chainApp.UregistryKeeper.AddTokenConfig(ctx, &uregistrytypes.TokenConfig{
Chain: "eip155:97",
Address: usdcAddress.String(),
Name: "USD Coin",
Symbol: "USDC",
Decimals: 6,
Enabled: true,
LiquidityCap: "1000000000000000000000000",
TokenType: 1,
NativeRepresentation: &uregistrytypes.NativeRepresentation{
Denom: "",
ContractAddress: prc20Address.String(),
},
})

// person B — a different sender on a different chain
personBSender := utils.GetDefaultAddresses().TargetAddr2

validUP := &uexecutortypes.UniversalPayload{
Expand All @@ -713,8 +744,9 @@ func TestInboundCEAFundsAndPayload(t *testing.T) {
VType: uexecutortypes.VerificationType(1),
}

// CEA inbound from eip155:97, but UEA origin is eip155:11155111
ceaInbound := &uexecutortypes.Inbound{
SourceChain: "eip155:11155111",
SourceChain: "eip155:97",
TxHash: "0xcea07",
Sender: personBSender,
Recipient: ueaAddrHex.String(),
Expand All @@ -739,12 +771,18 @@ func TestInboundCEAFundsAndPayload(t *testing.T) {
require.NoError(t, err)
}

// Verify the stored sender in VerifiedTxMetadata is the UEA owner, not personBSender
verified, found, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ceaInbound.SourceChain, ceaInbound.TxHash)
// Payload hash should be stored under UEA origin chain (eip155:11155111), NOT source chain (eip155:97)
ueaOriginChain := "eip155:11155111"
verified, found, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ueaOriginChain, ceaInbound.TxHash)
require.NoError(t, err)
require.True(t, found, "verified tx metadata should exist after execution")
require.True(t, found, "verified tx metadata should be stored under UEA origin chain")
require.NotEmpty(t, verified.PayloadHashes, "payload hashes should be stored")

// Should NOT be found under source chain
_, foundUnderSource, err := chainApp.UtxverifierKeeper.GetVerifiedInboundTxMetadata(ctx, ceaInbound.SourceChain, ceaInbound.TxHash)
require.NoError(t, err)
require.False(t, foundUnderSource, "verified tx metadata should NOT be stored under inbound source chain for CEA")

// The sender should be the UEA owner (testAddress), NOT personBSender
require.NotEqual(t, personBSender, verified.Sender,
"stored sender should NOT be the CEA executor")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func TestInboundSyntheticBridgePayload(t *testing.T) {

// Call your function to compute and store payload hash
ueModuleAddr, _ := app.UexecutorKeeper.GetUeModuleAddress(ctx)
err = app.UexecutorKeeper.StoreVerifiedPayloadHash(ctx, utx, ueaAddrHex, ueModuleAddr, utx.InboundTx.Sender)
err = app.UexecutorKeeper.StoreVerifiedPayloadHash(ctx, utx, ueaAddrHex, ueModuleAddr, utx.InboundTx.Sender, utx.InboundTx.SourceChain)
require.NoError(t, err)

// Verify payload hash stored in utxverifier
Expand Down
8 changes: 5 additions & 3 deletions x/uexecutor/keeper/execute_inbound_funds_and_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni
var receipt *evmtypes.MsgEthereumTxResponse
var ueaAddr common.Address
var isSmartContract bool
payloadSender := utx.InboundTx.Sender // default: inbound sender; overridden to UEA owner for CEA
payloadSender := utx.InboundTx.Sender // default: inbound sender; overridden to UEA owner for CEA
payloadChain := utx.InboundTx.SourceChain // default: inbound source chain; overridden to UEA origin chain for CEA

// Parse amount to check for zero-amount path
inboundAmount := new(big.Int)
Expand All @@ -55,8 +56,9 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni
if ueaCheckErr != nil {
execErr = fmt.Errorf("failed to verify UEA: %w", ueaCheckErr)
} else if isUEA {
// Use UEA owner as sender for payload hash verification
// Use UEA owner and origin chain for payload hash verification
payloadSender = origin.Owner
payloadChain = fmt.Sprintf("%s:%s", origin.ChainNamespace, origin.ChainId)
// UEA path: deposit PRC20 into the UEA (if amount > 0), then execute payload via UEA
if inboundAmount.Sign() > 0 {
receipt, execErr = k.depositPRC20(
Expand Down Expand Up @@ -248,7 +250,7 @@ func (k Keeper) ExecuteInboundFundsAndPayload(ctx context.Context, utx types.Uni
ueModuleAddr, _ := k.GetUeModuleAddress(ctx)

// --- Step 3: compute and store payload hash
payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr, payloadSender)
payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr, payloadSender, payloadChain)
if payloadHashErr != nil {
errorPcTx := types.PCTx{
Sender: ueModuleAddressStr,
Expand Down
8 changes: 5 additions & 3 deletions x/uexecutor/keeper/execute_inbound_gas_and_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive
var receipt *evmtypes.MsgEthereumTxResponse
var ueaAddr common.Address
var isSmartContract bool
payloadSender := utx.InboundTx.Sender // default: inbound sender; overridden to UEA owner for CEA
payloadSender := utx.InboundTx.Sender // default: inbound sender; overridden to UEA owner for CEA
payloadChain := utx.InboundTx.SourceChain // default: inbound source chain; overridden to UEA origin chain for CEA

shouldRevert := false
var revertReason string
Expand Down Expand Up @@ -63,8 +64,9 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive
if ueaCheckErr != nil {
execErr = fmt.Errorf("failed to verify UEA: %w", ueaCheckErr)
} else if isUEA {
// Use UEA owner as sender for payload hash verification
// Use UEA owner and origin chain for payload hash verification
payloadSender = origin.Owner
payloadChain = fmt.Sprintf("%s:%s", origin.ChainNamespace, origin.ChainId)
// UEA path: deposit + autoswap into the UEA (if amount > 0), then execute payload via UEA
if amount.Sign() > 0 {
prc20AddrHex := common.HexToAddress(tokenConfig.NativeRepresentation.ContractAddress)
Expand Down Expand Up @@ -252,7 +254,7 @@ func (k Keeper) ExecuteInboundGasAndPayload(ctx context.Context, utx types.Unive
ueModuleAddr, _ := k.GetUeModuleAddress(ctx)

// --- Step 6: payload hash
payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr, payloadSender)
payloadHashErr := k.StoreVerifiedPayloadHash(sdkCtx, utx, ueaAddr, ueModuleAddr, payloadSender, payloadChain)
if payloadHashErr != nil {
errorPcTx := types.PCTx{
Sender: ueModuleAddressStr,
Expand Down
4 changes: 3 additions & 1 deletion x/uexecutor/keeper/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ func (k Keeper) GetPayloadHashEVM(

// StoreVerifiedPayloadHash stores one payload hash for a given inbound tx.
// sender is the address to record as the verified sender (UEA owner for CEA, inbound sender otherwise).
// chain is the CAIP-2 chain identifier to store under (UEA origin chain for CEA, inbound source chain otherwise).
func (k Keeper) StoreVerifiedPayloadHash(
ctx sdk.Context,
utx types.UniversalTx, // struct containing InboundTx
ueaAddr common.Address,
ueModuleAccAddress common.Address,
sender string,
chain string,
) error {
// Convert to AbiUniversalPayload
abiPayload, err := types.NewAbiUniversalPayload(utx.InboundTx.UniversalPayload)
Expand Down Expand Up @@ -90,7 +92,7 @@ func (k Keeper) StoreVerifiedPayloadHash(
}

// Store in utxverifierKeeper
err = k.utxverifierKeeper.StoreVerifiedInboundTx(ctx, utx.InboundTx.SourceChain, utx.InboundTx.TxHash, verified)
err = k.utxverifierKeeper.StoreVerifiedInboundTx(ctx, chain, utx.InboundTx.TxHash, verified)
if err != nil {
return fmt.Errorf("failed to store verified tx: %w", err)
}
Expand Down
Loading