From e61a4e6b22b3eefdf9591525d05345701bc01cf2 Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 25 Oct 2024 12:17:09 +0800 Subject: [PATCH 1/3] fix [Contracts] Check string length when setting publish config #15 --- aggregator/package.json | 4 ++-- .../src/abstract/aggregator.abstract.ts | 24 ++++--------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/aggregator/package.json b/aggregator/package.json index c4b1fe2..539ef8c 100644 --- a/aggregator/package.json +++ b/aggregator/package.json @@ -13,8 +13,8 @@ "clear": "near contract call-function as-transaction ormpaggregator.guantong.testnet _clear_state json-args {} prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "test": "$npm_execpath run build && ava -- ./build/ormp_aggregator.wasm", "publish-external": "near contract call-function as-transaction ormpaggregator.guantong.testnet publish_external json-args '{\"request_id\": \"70021766616531051842153016788507494922593962344450640499185811468\",\"mpc_options\":{\"nonce\":\"2\",\"gas_limit\":\"1000000\",\"max_fee_per_gas\":\"305777608991\",\"max_priority_fee_per_gas\":\"2500000000\"}}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", - "report": "near contract call-function as-transaction ormpaggregator.guantong.testnet report json-args '{\"request_id\":\"70021766616531051842153016788507494922593962344450640499185811468\",\"answers\":[{\"data_source_name\":\"test-source\",\"result\":\"test-result\"}],\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '300.0 Tgas' attached-deposit '0.01 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", - "set-publish-config-event": "near contract call-function as-transaction ormpaggregator.guantong.testnet set_publish_chain_config json-args '{\"chain_id\":\"11155111\",\"xapi_address\":\"0x6984ebE378F8cb815546Cb68a98807C1fA121A81\",\"reporters_fee\":\"300\",\"publish_fee\":\"400\",\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", + "report": "near contract call-function as-transaction ormpaggregator.guantong.testnet report json-args '{\"request_id\":\"70021766616531051842153016788507494922593962344450640499185811470\",\"answers\":[{\"data_source_name\":\"test-source\",\"result\":\"test-result\"}],\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '300.0 Tgas' attached-deposit '1 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", + "set-publish-config-event": "near contract call-function as-transaction ormpaggregator.guantong.testnet set_publish_chain_config json-args '{\"chain_id\":\"11155111\",\"xapi_address\":\"0x6984ebE378F8cb815546Cb68a98807C1fA121A81\",\"reporters_fee\":\"12000000000000\",\"publish_fee\":\"2000000000000\",\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "sync-publish-config": "near contract call-function as-transaction ormpaggregator.guantong.testnet sync_publish_config_to_remote json-args '{\"chain_id\": \"11155111\",\"mpc_options\":{\"nonce\":\"1\",\"gas_limit\":\"200000\",\"max_fee_per_gas\":\"305777608991\",\"max_priority_fee_per_gas\":\"2500000000\"}}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", "add-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet add_data_source json-args '{\"name\":\"httpbin3\",\"url\":\"https://httpbin.org/anything\",\"method\":\"post\",\"headers\":{\"hello\":\"xapi\"},\"body_json\":{\"hello\":\"httpbin\"},\"result_path\":\"headers.host\",\"auth\":{\"place_path\":\"headers.Authorization\",\"value_path\":\"abcdefauth\"}}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "remove-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet remove_data_source json-args '{\"data_source_name\":\"httpbin\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", diff --git a/aggregator/src/abstract/aggregator.abstract.ts b/aggregator/src/abstract/aggregator.abstract.ts index dfbb3c0..770df6e 100644 --- a/aggregator/src/abstract/aggregator.abstract.ts +++ b/aggregator/src/abstract/aggregator.abstract.ts @@ -336,11 +336,11 @@ export abstract class Aggregator extends ContractBase { abstract set_publish_chain_config(publish_chain_config: PublishChainConfig): void; _set_publish_chain_config(publish_chain_config: PublishChainConfig): void { this._assert_operator(); - assert(publish_chain_config.chain_id != null, "chain_id can't be null."); - assert(publish_chain_config.xapi_address != null, "xapi_address can't be null."); - assert(publish_chain_config.reporters_fee != null, "reporters_fee can't be null."); - assert(publish_chain_config.publish_fee != null, "publish_fee can't be null."); - assert(publish_chain_config.reward_address != null, "reward_address can't be null."); + assert(publish_chain_config.chain_id != null && publish_chain_config.chain_id.length <= 20, "chain_id can't be null and the length should <= 20"); + assert(publish_chain_config.xapi_address != null && publish_chain_config.xapi_address.length == 42, "xapi_address can't be null and the length should be 42."); + assert(publish_chain_config.reporters_fee != null && publish_chain_config.reporters_fee.length <= 78, "reporters_fee can't be null and the length should <= 78"); + assert(publish_chain_config.publish_fee != null && publish_chain_config.publish_fee.length <= 78, "publish_fee can't be null and the length should <= 78"); + assert(publish_chain_config.reward_address != null && publish_chain_config.reward_address.length == 42, "reward_address can't be null and the length should be 42."); const _publish_config = new PublishChainConfig({ ...publish_chain_config }); this.publish_chain_config_lookup.set(publish_chain_config.chain_id, _publish_config); new SetPublishChainConfigEvent(_publish_config).emit(); @@ -350,13 +350,6 @@ export abstract class Aggregator extends ContractBase { _sync_publish_config_to_remote({ chain_id, mpc_options }: { chain_id: ChainId, mpc_options: MpcOptions }): NearPromise { this._check_mpc_options(mpc_options); - // assert(near.attachedDeposit() >= BigInt(this.mpc_config.attached_balance), `Attached: ${near.attachedDeposit()}, Require: ${this.mpc_config.attached_balance}`); - // let _surplus = near.attachedDeposit() - BigInt(this.mpc_config.attached_balance); - // if (_surplus > 0) { - // near.log(`refund more than required deposit ${_surplus} YOCTO to ${near.signerAccountId()}`); - // NearPromise.new(near.signerAccountId()).transfer(_surplus); - // } - const _latest_config = this.publish_chain_config_lookup.get(chain_id); assert(_latest_config != null, `No publish chain config for ${chain_id}`); @@ -638,13 +631,6 @@ export abstract class Aggregator extends ContractBase { _publish({ request_id, mpc_options }: { request_id: RequestId, mpc_options: MpcOptions }): NearPromise { this._check_mpc_options(mpc_options); - // assert(near.attachedDeposit() >= BigInt(this.mpc_config.attached_balance), `Attached: ${near.attachedDeposit()}, Require: ${this.mpc_config.attached_balance}`); - // let _surplus = near.attachedDeposit() - BigInt(this.mpc_config.attached_balance); - // if (_surplus > 0) { - // near.log(`refund more than required deposit ${_surplus} YOCTO to ${near.signerAccountId()}`); - // NearPromise.new(near.signerAccountId()).transfer(_surplus); - // } - const _response = this.response_lookup.get(request_id); assert(_response != null, `Response for ${request_id} does not exist`); assert(_response.status == RequestStatus[RequestStatus.AGGREGATED] || _response.status == RequestStatus[RequestStatus.PUBLISHED], `Response status is ${_response.status}, can't be published`); From 63113013fd12b27c6b2ca1a8d521cfdc00755dc1 Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 25 Oct 2024 14:32:32 +0800 Subject: [PATCH 2/3] fix [Contracts] Fix refund #16 --- aggregator/package.json | 6 +++--- .../src/abstract/aggregator.abstract.ts | 21 +++++++++---------- aggregator/src/ormp.aggregator.ts | 4 ++-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/aggregator/package.json b/aggregator/package.json index 539ef8c..8f84c8f 100644 --- a/aggregator/package.json +++ b/aggregator/package.json @@ -13,11 +13,11 @@ "clear": "near contract call-function as-transaction ormpaggregator.guantong.testnet _clear_state json-args {} prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "test": "$npm_execpath run build && ava -- ./build/ormp_aggregator.wasm", "publish-external": "near contract call-function as-transaction ormpaggregator.guantong.testnet publish_external json-args '{\"request_id\": \"70021766616531051842153016788507494922593962344450640499185811468\",\"mpc_options\":{\"nonce\":\"2\",\"gas_limit\":\"1000000\",\"max_fee_per_gas\":\"305777608991\",\"max_priority_fee_per_gas\":\"2500000000\"}}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", - "report": "near contract call-function as-transaction ormpaggregator.guantong.testnet report json-args '{\"request_id\":\"70021766616531051842153016788507494922593962344450640499185811470\",\"answers\":[{\"data_source_name\":\"test-source\",\"result\":\"test-result\"}],\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '300.0 Tgas' attached-deposit '1 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", + "report": "near contract call-function as-transaction ormpaggregator.guantong.testnet report json-args '{\"request_id\":\"70021766616531051842153016788507494922593962344450640499185811470\",\"answers\":[{\"data_source_name\":\"test-source\",\"result\":\"test-result\"}],\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '300.0 Tgas' attached-deposit '6406250000000000000000 yoctonear' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", "set-publish-config-event": "near contract call-function as-transaction ormpaggregator.guantong.testnet set_publish_chain_config json-args '{\"chain_id\":\"11155111\",\"xapi_address\":\"0x6984ebE378F8cb815546Cb68a98807C1fA121A81\",\"reporters_fee\":\"12000000000000\",\"publish_fee\":\"2000000000000\",\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "sync-publish-config": "near contract call-function as-transaction ormpaggregator.guantong.testnet sync_publish_config_to_remote json-args '{\"chain_id\": \"11155111\",\"mpc_options\":{\"nonce\":\"1\",\"gas_limit\":\"200000\",\"max_fee_per_gas\":\"305777608991\",\"max_priority_fee_per_gas\":\"2500000000\"}}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", - "add-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet add_data_source json-args '{\"name\":\"httpbin3\",\"url\":\"https://httpbin.org/anything\",\"method\":\"post\",\"headers\":{\"hello\":\"xapi\"},\"body_json\":{\"hello\":\"httpbin\"},\"result_path\":\"headers.host\",\"auth\":{\"place_path\":\"headers.Authorization\",\"value_path\":\"abcdefauth\"}}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", - "remove-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet remove_data_source json-args '{\"data_source_name\":\"httpbin\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", + "add-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet add_data_source json-args '{\"name\":\"httpbin4\",\"url\":\"https://httpbin.org/anything\",\"method\":\"post\",\"headers\":{\"hello\":\"xapi\"},\"body_json\":{\"hello\":\"httpbin\"},\"result_path\":\"headers.host\",\"auth\":{\"place_path\":\"headers.Authorization\",\"value_path\":\"abcdefauth\"}}' prepaid-gas '100.0 Tgas' attached-deposit '3671875000000000000000 yoctonear' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", + "remove-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet remove_data_source json-args '{\"data_source_name\":\"httpbin4\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "estimate-report-size": "near contract call-function as-read-only ormpaggregator.guantong.testnet estimate_report_deposit json-args '{\"request_id\":\"111111\",\"answers\":[{\"data_source_name\":\"123\",\"result\":\"456\"}]}' network-config testnet now", "ava": "ava" }, diff --git a/aggregator/src/abstract/aggregator.abstract.ts b/aggregator/src/abstract/aggregator.abstract.ts index 770df6e..d6e888c 100644 --- a/aggregator/src/abstract/aggregator.abstract.ts +++ b/aggregator/src/abstract/aggregator.abstract.ts @@ -474,14 +474,9 @@ export abstract class Aggregator extends ContractBase { const _deposit = near.attachedDeposit(); const _required_deposit = this._storage_deposit(__report); assert( - _deposit >= _required_deposit, - `Insufficient deposit, deposit: ${_deposit}, required: ${_required_deposit}` + _deposit == _required_deposit, + `Wrong deposit, deposit: ${_deposit}, required: ${_required_deposit}` ); - let _surplus = near.attachedDeposit() - _required_deposit; - if (_surplus > 0) { - near.log(`refund more than required deposit ${_surplus} YOCTO to ${near.signerAccountId()}`); - NearPromise.new(near.signerAccountId()).transfer(_surplus); - } let _response = this.response_lookup.get(request_id); if (_response == null) { @@ -514,8 +509,8 @@ export abstract class Aggregator extends ContractBase { return this._try_aggregate({ request_id }); } - abstract add_data_source(data_source: DataSource): void; - _add_data_source(data_source: DataSource): void { + abstract add_data_source(data_source: DataSource): NearPromise; + _add_data_source(data_source: DataSource): NearPromise { this._assert_operator(); assert(data_source.name != null, "Datasource name is null"); @@ -528,9 +523,10 @@ export abstract class Aggregator extends ContractBase { const _required_deposit = this._storage_deposit(data_source); const _surplus = near.attachedDeposit() - _required_deposit; assert(_surplus >= 0, `Attached: ${near.attachedDeposit()}, Require: ${_required_deposit}`) + let promise = null; if (_surplus > 0) { - near.log(`refund more than required deposit ${_surplus} YOCTO to ${near.signerAccountId()}`); - NearPromise.new(near.signerAccountId()).transfer(_surplus); + near.log(`Attached: ${near.attachedDeposit()}, Require: ${_required_deposit}, refund more than required deposit ${_surplus} YOCTO to ${near.signerAccountId()}`); + promise = NearPromise.new(near.signerAccountId()).transfer(_surplus); } const checkMethod = data_source.method.toString(); @@ -560,6 +556,9 @@ export abstract class Aggregator extends ContractBase { this.data_sources.set(data_source.name, data_source); new AddDataSourceEvent(data_source).emit(); + if (promise) { + return promise.asReturn(); + } } abstract remove_data_source({ data_source_name }: { data_source_name: string }): void; diff --git a/aggregator/src/ormp.aggregator.ts b/aggregator/src/ormp.aggregator.ts index 7b25a40..9ca5b55 100644 --- a/aggregator/src/ormp.aggregator.ts +++ b/aggregator/src/ormp.aggregator.ts @@ -166,8 +166,8 @@ class OrmpAggregator extends Aggregator { } @call({ payableFunction: true }) - add_data_source(data_source: DataSource): void { - super._add_data_source(data_source); + add_data_source(data_source: DataSource): NearPromise { + return super._add_data_source(data_source); } @call({}) From 57ce242818749a493f6b002f1c7e8957c86e796c Mon Sep 17 00:00:00 2001 From: Guantong Date: Fri, 25 Oct 2024 14:47:43 +0800 Subject: [PATCH 3/3] query json and more methods --- aggregator/package.json | 2 +- .../src/abstract/aggregator.abstract.ts | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/aggregator/package.json b/aggregator/package.json index 8f84c8f..5f9a39d 100644 --- a/aggregator/package.json +++ b/aggregator/package.json @@ -16,7 +16,7 @@ "report": "near contract call-function as-transaction ormpaggregator.guantong.testnet report json-args '{\"request_id\":\"70021766616531051842153016788507494922593962344450640499185811470\",\"answers\":[{\"data_source_name\":\"test-source\",\"result\":\"test-result\"}],\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '300.0 Tgas' attached-deposit '6406250000000000000000 yoctonear' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", "set-publish-config-event": "near contract call-function as-transaction ormpaggregator.guantong.testnet set_publish_chain_config json-args '{\"chain_id\":\"11155111\",\"xapi_address\":\"0x6984ebE378F8cb815546Cb68a98807C1fA121A81\",\"reporters_fee\":\"12000000000000\",\"publish_fee\":\"2000000000000\",\"reward_address\":\"0x9F33a4809aA708d7a399fedBa514e0A0d15EfA85\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "sync-publish-config": "near contract call-function as-transaction ormpaggregator.guantong.testnet sync_publish_config_to_remote json-args '{\"chain_id\": \"11155111\",\"mpc_options\":{\"nonce\":\"1\",\"gas_limit\":\"200000\",\"max_fee_per_gas\":\"305777608991\",\"max_priority_fee_per_gas\":\"2500000000\"}}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as guantong.testnet network-config testnet sign-with-legacy-keychain send", - "add-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet add_data_source json-args '{\"name\":\"httpbin4\",\"url\":\"https://httpbin.org/anything\",\"method\":\"post\",\"headers\":{\"hello\":\"xapi\"},\"body_json\":{\"hello\":\"httpbin\"},\"result_path\":\"headers.host\",\"auth\":{\"place_path\":\"headers.Authorization\",\"value_path\":\"abcdefauth\"}}' prepaid-gas '100.0 Tgas' attached-deposit '3671875000000000000000 yoctonear' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", + "add-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet add_data_source json-args '{\"name\":\"httpbin4\",\"url\":\"https://httpbin.org/anything\",\"method\":\"get\",\"headers\":{\"hello\":\"xapi\"},\"query_json\":{\"hello\":\"httpbin\"},\"result_path\":\"headers.host\",\"auth\":{\"place_path\":\"headers.Authorization\",\"value_path\":\"abcdefauth\"}}' prepaid-gas '100.0 Tgas' attached-deposit '3671875000000000000000 yoctonear' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "remove-data-source": "near contract call-function as-transaction ormpaggregator.guantong.testnet remove_data_source json-args '{\"data_source_name\":\"httpbin4\"}' prepaid-gas '100.0 Tgas' attached-deposit '0 NEAR' sign-as ormpaggregator.guantong.testnet network-config testnet sign-with-legacy-keychain send", "estimate-report-size": "near contract call-function as-read-only ormpaggregator.guantong.testnet estimate_report_deposit json-args '{\"request_id\":\"111111\",\"answers\":[{\"data_source_name\":\"123\",\"result\":\"456\"}]}' network-config testnet now", "ava": "ava" diff --git a/aggregator/src/abstract/aggregator.abstract.ts b/aggregator/src/abstract/aggregator.abstract.ts index d6e888c..ce521b7 100644 --- a/aggregator/src/abstract/aggregator.abstract.ts +++ b/aggregator/src/abstract/aggregator.abstract.ts @@ -15,7 +15,10 @@ export enum RequestStatus { export enum RequestMethod { GET, - POST + POST, + PUT, + DELETE, + PATCH } export class PublishChainConfig { @@ -60,16 +63,18 @@ export class DataSource { method: string; headers: Object; body_json: Object; + query_json: Object; // https://docs.api3.org/reference/ois/latest/reserved-parameters.html#path, split by `,` result_path: string; auth: DataAuth; - constructor({ name, url, method, headers, body_json, result_path, auth }: { name: string, url: string, method: string, headers: Object, body_json: Object, result_path: string, auth: DataAuth }) { + constructor({ name, url, method, headers, body_json, query_json, result_path, auth }: { name: string, url: string, method: string, headers: Object, body_json: Object, query_json: Object, result_path: string, auth: DataAuth }) { this.name = name; this.url = url; this.method = method; this.headers = headers; this.body_json = body_json; + this.query_json = query_json; this.result_path = result_path; this.auth = auth; } @@ -534,8 +539,14 @@ export abstract class Aggregator extends ContractBase { data_source.method = RequestMethod[RequestMethod.GET]; } else if (checkMethod.toUpperCase() == "POST") { data_source.method = RequestMethod[RequestMethod.POST]; + } else if (checkMethod.toUpperCase() == "PUT") { + data_source.method = RequestMethod[RequestMethod.PUT]; + } else if (checkMethod.toUpperCase() == "DELETE") { + data_source.method = RequestMethod[RequestMethod.DELETE]; + } else if (checkMethod.toUpperCase() == "PATCH") { + data_source.method = RequestMethod[RequestMethod.PATCH]; } else { - assert(false, "method should be POST or GET"); + assert(false, "method should be in [GET, POST, PUT, DELETE, PATCH]"); } if (data_source.headers) { @@ -544,6 +555,9 @@ export abstract class Aggregator extends ContractBase { if (data_source.body_json) { assert(typeof data_source.body_json == "object", "body_json must be object"); } + if (data_source.query_json) { + assert(typeof data_source.query_json == "object", "query_json must be object"); + } if (data_source.auth) { assert(