Skip to content

Commit 949588c

Browse files
authored
feat(foreign-tx): svm support in contract interface (#4136)
1 parent 0e923dc commit 949588c

9 files changed

Lines changed: 429 additions & 147 deletions

crates/contract/src/snapshots/mpc_contract__foreign_chains_metadata__tests__foreign_chains_metadata_borsh_schema__should_not_change.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ BorshSchemaContainer {
105105
"Adi",
106106
"ForeignChain__Adi",
107107
),
108+
(
109+
15,
110+
"Fogo",
111+
"ForeignChain__Fogo",
112+
),
108113
],
109114
},
110115
"ForeignChainRpcWhitelist": Struct {
@@ -148,6 +153,9 @@ BorshSchemaContainer {
148153
"ForeignChain__Ethereum": Struct {
149154
fields: Empty,
150155
},
156+
"ForeignChain__Fogo": Struct {
157+
fields: Empty,
158+
},
151159
"ForeignChain__HyperEvm": Struct {
152160
fields: Empty,
153161
},

crates/contract/tests/sandbox/common.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ use near_mpc_contract_interface::types::{
3131
AptosAddress, AptosEvent, AptosExtractedValue, AptosExtractor, AptosFinality, AptosRpcRequest,
3232
AptosTxId, Curve, DomainConfig, DomainId, DomainPurpose, ProposeUpdateArgs, Protocol,
3333
ReconstructionThreshold, SuiAddress, SuiEvent, SuiExtractedValue, SuiExtractor, SuiFinality,
34-
SuiRpcRequest, SuiTxId, SupportedForeignChains, TonAddress, TonCellBody, TonExtractedValue,
35-
TonExtractor, TonFinality, TonLog, TonRpcRequest, TonTxId,
34+
SuiRpcRequest, SuiTxId, SupportedForeignChains, SvmAddress, SvmExtractedValue, SvmExtractor,
35+
SvmFinality, SvmInnerInstruction, SvmRpcRequest, SvmTxId, TonAddress, TonCellBody,
36+
TonExtractedValue, TonExtractor, TonFinality, TonLog, TonRpcRequest, TonTxId,
3637
};
3738
use near_mpc_contract_interface::{
3839
method_names,
@@ -936,3 +937,32 @@ pub fn sui_request() -> ForeignChainRpcRequest {
936937
extractors: vec![SuiExtractor::Event { event_index: 0 }],
937938
})
938939
}
940+
941+
pub fn solana_request() -> ForeignChainRpcRequest {
942+
ForeignChainRpcRequest::Solana(svm_rpc_request())
943+
}
944+
945+
pub fn fogo_request() -> ForeignChainRpcRequest {
946+
ForeignChainRpcRequest::Fogo(svm_rpc_request())
947+
}
948+
949+
fn svm_rpc_request() -> SvmRpcRequest {
950+
SvmRpcRequest {
951+
tx_id: SvmTxId([0xbb; 64]),
952+
finality: SvmFinality::Finalized,
953+
extractors: vec![SvmExtractor::InnerInstruction {
954+
instruction_index: 0,
955+
inner_instruction_index: 0,
956+
}],
957+
}
958+
}
959+
960+
pub fn svm_extracted_values() -> Vec<ExtractedValue> {
961+
vec![ExtractedValue::SvmExtractedValue(
962+
SvmExtractedValue::InnerInstruction(SvmInnerInstruction {
963+
program_id: SvmAddress([1; 32]),
964+
accounts: vec![SvmAddress([2; 32]), SvmAddress([3; 32])],
965+
data: vec![0xde, 0xad, 0xbe, 0xef],
966+
}),
967+
)]
968+
}

crates/contract/tests/sandbox/foreign_chain_request.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use crate::sandbox::common::{
55
arbitrum_evm_request, avalanche_evm_request,
66
await_pending_foreign_tx_request_observed_on_contract, base_evm_request,
77
bitcoin_extracted_values, bitcoin_request, bnb_evm_request, bogus_ton_log_extracted_value,
8-
ethereum_evm_request, evm_block_hash_extracted_values, hyper_evm_request, polygon_evm_request,
9-
register_foreign_chain_configuration, sign_foreign_tx_response, starknet_extracted_values,
10-
starknet_request, sui_extracted_values, sui_request, ton_request,
8+
ethereum_evm_request, evm_block_hash_extracted_values, fogo_request, hyper_evm_request,
9+
polygon_evm_request, register_foreign_chain_configuration, sign_foreign_tx_response,
10+
solana_request, starknet_extracted_values, starknet_request, sui_extracted_values, sui_request,
11+
svm_extracted_values, ton_request,
1112
};
1213
use crate::sandbox::utils::transactions::CallMpcContract;
1314
use near_mpc_contract_interface::method_names;
@@ -35,6 +36,8 @@ const SIGNATURE_TIMEOUT_BLOCKS: u64 = 200;
3536
#[case::sui(sui_request(), sui_extracted_values())]
3637
#[case::avalanche(avalanche_evm_request(), evm_block_hash_extracted_values())]
3738
#[case::adi(adi_evm_request(), evm_block_hash_extracted_values())]
39+
#[case::solana(solana_request(), svm_extracted_values())]
40+
#[case::fogo(fogo_request(), svm_extracted_values())]
3841
#[tokio::test]
3942
async fn verify_foreign_transaction__should_succeed(
4043
#[case] rpc_request: ForeignChainRpcRequest,
@@ -326,6 +329,8 @@ async fn verify_foreign_transaction__should_succeed_when_response_matches_expect
326329
#[case::sui(sui_request())]
327330
#[case::avalanche(avalanche_evm_request())]
328331
#[case::adi(adi_evm_request())]
332+
#[case::solana(solana_request())]
333+
#[case::fogo(fogo_request())]
329334
#[tokio::test]
330335
async fn verify_foreign_transaction__should_reject_without_policy(
331336
#[case] rpc_request: ForeignChainRpcRequest,
@@ -372,6 +377,8 @@ async fn verify_foreign_transaction__should_reject_without_policy(
372377
#[case::sui(sui_request())]
373378
#[case::avalanche(avalanche_evm_request())]
374379
#[case::adi(adi_evm_request())]
380+
#[case::solana(solana_request())]
381+
#[case::fogo(fogo_request())]
375382
#[tokio::test]
376383
async fn verify_foreign_transaction__should_timeout_without_response(
377384
#[case] rpc_request: ForeignChainRpcRequest,

crates/contract/tests/snapshots/abi__abi_has_not_changed.snap

Lines changed: 120 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ expression: abi
266266
14,
267267
"Adi",
268268
"ForeignChain__Adi"
269+
],
270+
[
271+
15,
272+
"Fogo",
273+
"ForeignChain__Fogo"
269274
]
270275
]
271276
}
@@ -297,6 +302,9 @@ expression: abi
297302
"ForeignChain__Ethereum": {
298303
"Struct": null
299304
},
305+
"ForeignChain__Fogo": {
306+
"Struct": null
307+
},
300308
"ForeignChain__HyperEvm": {
301309
"Struct": null
302310
},
@@ -3129,6 +3137,11 @@ expression: abi
31293137
14,
31303138
"Adi",
31313139
"ForeignChain__Adi"
3140+
],
3141+
[
3142+
15,
3143+
"Fogo",
3144+
"ForeignChain__Fogo"
31323145
]
31333146
]
31343147
}
@@ -3160,6 +3173,9 @@ expression: abi
31603173
"ForeignChain__Ethereum": {
31613174
"Struct": null
31623175
},
3176+
"ForeignChain__Fogo": {
3177+
"Struct": null
3178+
},
31633179
"ForeignChain__HyperEvm": {
31643180
"Struct": null
31653181
},
@@ -4108,7 +4124,8 @@ expression: abi
41084124
"Aptos",
41094125
"Sui",
41104126
"Avalanche",
4111-
"Adi"
4127+
"Adi",
4128+
"Fogo"
41124129
]
41134130
},
41144131
"ForeignChainConfiguration": {
@@ -4151,7 +4168,7 @@ expression: abi
41514168
],
41524169
"properties": {
41534170
"Solana": {
4154-
"$ref": "#/definitions/SolanaRpcRequest"
4171+
"$ref": "#/definitions/SvmRpcRequest"
41554172
}
41564173
},
41574174
"additionalProperties": false
@@ -4299,6 +4316,18 @@ expression: abi
42994316
}
43004317
},
43014318
"additionalProperties": false
4319+
},
4320+
{
4321+
"type": "object",
4322+
"required": [
4323+
"Fogo"
4324+
],
4325+
"properties": {
4326+
"Fogo": {
4327+
"$ref": "#/definitions/SvmRpcRequest"
4328+
}
4329+
},
4330+
"additionalProperties": false
43024331
}
43034332
]
43044333
},
@@ -5736,92 +5765,6 @@ expression: abi
57365765
}
57375766
]
57385767
},
5739-
"SolanaExtractor": {
5740-
"oneOf": [
5741-
{
5742-
"type": "object",
5743-
"required": [
5744-
"SolanaProgramIdIndex"
5745-
],
5746-
"properties": {
5747-
"SolanaProgramIdIndex": {
5748-
"type": "object",
5749-
"required": [
5750-
"ix_index"
5751-
],
5752-
"properties": {
5753-
"ix_index": {
5754-
"type": "integer",
5755-
"format": "uint32",
5756-
"minimum": 0.0
5757-
}
5758-
}
5759-
}
5760-
},
5761-
"additionalProperties": false
5762-
},
5763-
{
5764-
"type": "object",
5765-
"required": [
5766-
"SolanaDataHash"
5767-
],
5768-
"properties": {
5769-
"SolanaDataHash": {
5770-
"type": "object",
5771-
"required": [
5772-
"ix_index"
5773-
],
5774-
"properties": {
5775-
"ix_index": {
5776-
"type": "integer",
5777-
"format": "uint32",
5778-
"minimum": 0.0
5779-
}
5780-
}
5781-
}
5782-
},
5783-
"additionalProperties": false
5784-
}
5785-
]
5786-
},
5787-
"SolanaFinality": {
5788-
"type": "string",
5789-
"enum": [
5790-
"Processed",
5791-
"Confirmed",
5792-
"Finalized"
5793-
]
5794-
},
5795-
"SolanaRpcRequest": {
5796-
"type": "object",
5797-
"required": [
5798-
"extractors",
5799-
"finality",
5800-
"tx_id"
5801-
],
5802-
"properties": {
5803-
"extractors": {
5804-
"type": "array",
5805-
"items": {
5806-
"$ref": "#/definitions/SolanaExtractor"
5807-
}
5808-
},
5809-
"finality": {
5810-
"$ref": "#/definitions/SolanaFinality"
5811-
},
5812-
"tx_id": {
5813-
"$ref": "#/definitions/SolanaTxId"
5814-
}
5815-
}
5816-
},
5817-
"SolanaTxId": {
5818-
"type": "array",
5819-
"items": {
5820-
"type": "integer",
5821-
"format": "uint8",
5822-
"minimum": 0.0
5823-
}
5824-
},
58255768
"StarknetExtractor": {
58265769
"oneOf": [
58275770
{
@@ -5957,6 +5900,95 @@ expression: abi
59575900
},
59585901
"uniqueItems": true
59595902
},
5903+
"SvmAddress": {
5904+
"type": "string",
5905+
"pattern": "^(?:[0-9A-Fa-f]{2})*$"
5906+
},
5907+
"SvmExtractor": {
5908+
"oneOf": [
5909+
{
5910+
"type": "object",
5911+
"required": [
5912+
"InnerInstruction"
5913+
],
5914+
"properties": {
5915+
"InnerInstruction": {
5916+
"type": "object",
5917+
"required": [
5918+
"inner_instruction_index",
5919+
"instruction_index"
5920+
],
5921+
"properties": {
5922+
"inner_instruction_index": {
5923+
"type": "integer",
5924+
"format": "uint64",
5925+
"minimum": 0.0
5926+
},
5927+
"instruction_index": {
5928+
"type": "integer",
5929+
"format": "uint64",
5930+
"minimum": 0.0
5931+
}
5932+
}
5933+
}
5934+
},
5935+
"additionalProperties": false
5936+
},
5937+
{
5938+
"type": "object",
5939+
"required": [
5940+
"AccountState"
5941+
],
5942+
"properties": {
5943+
"AccountState": {
5944+
"type": "object",
5945+
"required": [
5946+
"pubkey"
5947+
],
5948+
"properties": {
5949+
"pubkey": {
5950+
"$ref": "#/definitions/SvmAddress"
5951+
}
5952+
}
5953+
}
5954+
},
5955+
"additionalProperties": false
5956+
}
5957+
]
5958+
},
5959+
"SvmFinality": {
5960+
"type": "string",
5961+
"enum": [
5962+
"Confirmed",
5963+
"Finalized"
5964+
]
5965+
},
5966+
"SvmRpcRequest": {
5967+
"type": "object",
5968+
"required": [
5969+
"extractors",
5970+
"finality",
5971+
"tx_id"
5972+
],
5973+
"properties": {
5974+
"extractors": {
5975+
"type": "array",
5976+
"items": {
5977+
"$ref": "#/definitions/SvmExtractor"
5978+
}
5979+
},
5980+
"finality": {
5981+
"$ref": "#/definitions/SvmFinality"
5982+
},
5983+
"tx_id": {
5984+
"$ref": "#/definitions/SvmTxId"
5985+
}
5986+
}
5987+
},
5988+
"SvmTxId": {
5989+
"type": "string",
5990+
"pattern": "^(?:[0-9A-Fa-f]{2}){64}$"
5991+
},
59605992
"TcbInfo": {
59615993
"description": "Trusted Computing Base information structure",
59625994
"type": "object",

0 commit comments

Comments
 (0)