diff --git a/TNLS-Gateways/public-gateway/script/UpgradeScript.s.sol b/TNLS-Gateways/public-gateway/script/UpgradeScript.s.sol index bf370fc..9c2691c 100644 --- a/TNLS-Gateways/public-gateway/script/UpgradeScript.s.sol +++ b/TNLS-Gateways/public-gateway/script/UpgradeScript.s.sol @@ -28,10 +28,10 @@ contract UpgradeScript is Script { // Deploy New Gateway Logic Contract newGatewayLogic = new Gateway(); - gatewayProxyAdmin = ProxyAdmin(0x7C0f8810f989cB92533b09c3535B1EfA80393EAD); + gatewayProxyAdmin = ProxyAdmin(0x9eA72D83533D8B753d000D9C233a80CC08FFb072); bytes memory selector = abi.encodeWithSelector(Gateway.upgradeHandler.selector); - gatewayProxyAdmin.upgradeAndCall(ITransparentUpgradeableProxy(0xBFE44aF8e40B6468946e9AA88fe2c6c9D0352F62), address(newGatewayLogic),selector); + gatewayProxyAdmin.upgradeAndCall(ITransparentUpgradeableProxy(0x286B1e6B58a913E457509f0C30Ad4393C78f4F84), address(newGatewayLogic),selector); vm.stopBroadcast(); } diff --git a/TNLS-Gateways/public-gateway/src/Gateway.sol b/TNLS-Gateways/public-gateway/src/Gateway.sol index f8160ca..4a50b62 100644 --- a/TNLS-Gateways/public-gateway/src/Gateway.sol +++ b/TNLS-Gateways/public-gateway/src/Gateway.sol @@ -13,13 +13,6 @@ contract GatewayProxy is TransparentUpgradeableProxy { constructor(address _logic, address admin_, bytes memory _data) TransparentUpgradeableProxy(_logic, admin_, _data) {} } - /*////////////////////////////////////////////////////////////// - Secret VRF Interface - //////////////////////////////////////////////////////////////*/ -interface IRandomness { - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external; -} - contract Gateway is Initializable { /*////////////////////////////////////////////////////////////// Constants @@ -27,10 +20,10 @@ contract Gateway is Initializable { //Use hard coded constant values instead of storage variables for Secret VRF, saves around 10,000+ in gas per TX. //Since contract is upgradeable, we can update these values as well with it. - bytes constant routing_info = "secret1a9jvkwanwgs66222a74p607reh333nfsspgp93"; + bytes constant routing_info = "secret14hlku6qen0tkhfq0cklx02hcdu9jph8un4lsga"; bytes constant routing_code_hash = "ba0006753cb18a8b12fe266707289098bfb8a3ae83de54ecece591231ada2abf"; string constant task_destination_network = "secret-4"; - address constant secret_gateway_signer_address = 0x9199301b86c1eC0C180B51B1CFb6B4966A0D6bFf; + address constant secret_gateway_signer_address = 0x1b153e8fc101c2c6C9e0a9250aca99e957354a8E; /*////////////////////////////////////////////////////////////// @@ -49,6 +42,7 @@ contract Gateway is Initializable { string task_destination_network; string handle; bytes12 nonce; + uint32 callback_gas_limit; bytes payload; bytes payload_signature; } @@ -101,6 +95,9 @@ contract Gateway is Initializable { /// @notice thrown when the user requests more Random Words than allowed error TooManyVRFRandomWordsRequested(); + /// @notice thrown when the paid fee was lower than expected: + error PaidRequestFeeTooLow(); + /*////////////////////////////////////////////////////////////// Helpers //////////////////////////////////////////////////////////////*/ @@ -268,7 +265,7 @@ contract Gateway is Initializable { Maintainance Functions //////////////////////////////////////////////////////////////*/ - /// @notice Increase the task_id to check for problems + /// @notice Increase the task_id if needed /// @param _newTaskId the new task_id function increaseTaskId(uint256 _newTaskId) external onlyOwner { @@ -276,6 +273,24 @@ contract Gateway is Initializable { taskId = _newTaskId; } + /// @notice Payout the paid balance to the owner + + function payoutBalance() external onlyOwner { + payable(owner).transfer(address(this).balance); + } + + /*////////////////////////////////////////////////////////////// + Gas Price Payment Functions + //////////////////////////////////////////////////////////////*/ + + /// @notice Increase the task_id to check for problems + /// @param _callbackGasLimit the Callback Gas Limit + + function estimateRequestPrice(uint32 _callbackGasLimit) private view returns (uint256) { + uint256 baseFee = _callbackGasLimit*tx.gasprice; + return baseFee; + } + /*////////////////////////////////////////////////////////////// Pre Execution //////////////////////////////////////////////////////////////*/ @@ -293,6 +308,10 @@ contract Gateway is Initializable { ExecutionInfo calldata _info) external payable { + if (estimateRequestPrice(_info.callback_gas_limit) > msg.value) { + revert PaidRequestFeeTooLow(); + } + // Payload hash verification if (keccak256(bytes.concat("\x19Ethereum Signed Message:\n32", keccak256(_info.payload))) != _payloadHash) { revert InvalidPayloadHash(); @@ -335,6 +354,10 @@ contract Gateway is Initializable { revert TooManyVRFRandomWordsRequested(); } + if (estimateRequestPrice(_callbackGasLimit) > msg.value) { + revert PaidRequestFeeTooLow(); + } + //Encode the callback_address as Base64 string memory callback_address = encodeBase64(bytes.concat(bytes20(msg.sender))); @@ -361,6 +384,7 @@ contract Gateway is Initializable { task_destination_network: task_destination_network, handle: "request_random", nonce: bytes12(0), + callback_gas_limit:_callbackGasLimit, payload: payload, payload_signature: new bytes(64) // empty signature, fill with 0 bytes }); @@ -432,19 +456,20 @@ contract Gateway is Initializable { // Continue with the function execution // Additional conversion for Secret VRF into uint256[] if callback_selector matches the fullfillRandomWords selector. - if (_info.callback_selector == bytes4(0x38ba4614)) { + bool callbackSuccessful; + if (_info.callback_selector == 0x38ba4614) { uint256[] memory randomWords = bytesToUint256Array(_info.result); - IRandomness randomness = IRandomness(address(_info.callback_address)); - randomness.fulfillRandomWords(_taskId, randomWords); + (callbackSuccessful, ) = address(_info.callback_address).call( + abi.encodeWithSelector(0x38ba4614, _taskId, randomWords) + ); } else { - bool val; - (val, ) = address(_info.callback_address).call{gas: uint32(_info.callback_gas_limit)}( + (callbackSuccessful, ) = address(_info.callback_address).call( abi.encodeWithSelector(_info.callback_selector, _taskId, _info.result) ); - if (!val) { - revert CallbackError(); - } + } + if (!callbackSuccessful) { + revert CallbackError(); } } diff --git a/TNLS-Gateways/public-gateway/test/Contract.t.sol b/TNLS-Gateways/public-gateway/test/Contract.t.sol index 36b6ff9..9b906e4 100644 --- a/TNLS-Gateways/public-gateway/test/Contract.t.sol +++ b/TNLS-Gateways/public-gateway/test/Contract.t.sol @@ -187,6 +187,7 @@ contract ContractTest is Test { task_destination_network: "pulsar-3", handle: "some kinda handle", nonce: "ssssssssssss", + callback_gas_limit: 300000, payload: payload, payload_signature: getPayloadSignature(payload, 5) }); @@ -220,6 +221,7 @@ contract ContractTest is Test { task_destination_network: "pulsar-3", handle: "some kinda handle", nonce: "ssssssssssss", + callback_gas_limit: 300000, payload: payload, payload_signature: getPayloadSignature(payload, 7) }); @@ -319,11 +321,12 @@ contract ContractTest is Test { task_destination_network: "pulsar-3", handle: "some kinda handle", nonce: "ssssssssssss", + callback_gas_limit: 300000, payload: payload, payload_signature: payloadSignature }); - gateway.send(payloadHash, userAddress,routingInfo, assembledInfo ); + gateway.send(payloadHash, userAddress, routingInfo, assembledInfo ); (bytes31 tempPayloadHash,) = gateway.tasks(1); assertEq(tempPayloadHash, sliceLastByte(payloadHash)); diff --git a/TNLS-Gateways/secret/contract.wasm.gz b/TNLS-Gateways/secret/contract.wasm.gz index 88a9c35..d67c76a 100644 Binary files a/TNLS-Gateways/secret/contract.wasm.gz and b/TNLS-Gateways/secret/contract.wasm.gz differ diff --git a/TNLS-Gateways/secret/src/contract.rs b/TNLS-Gateways/secret/src/contract.rs index c39f834..26c5b62 100644 --- a/TNLS-Gateways/secret/src/contract.rs +++ b/TNLS-Gateways/secret/src/contract.rs @@ -13,7 +13,7 @@ use crate::{ ExecuteMsg, InputResponse, InstantiateMsg, PostExecutionMsg, PreExecutionMsg, PublicKeyResponse, QueryMsg, ResponseStatus::Success, SecretMsg, }, - state::{KeyPair, State, Task, TaskInfo, CONFIG, CREATOR, MY_ADDRESS, TASK_MAP}, + state::{KeyPair, State, Task, TaskInfo, ResultInfo, CONFIG, CREATOR, MY_ADDRESS, TASK_MAP, RESULT_MAP}, PrivContractHandleMsg, }; @@ -86,7 +86,7 @@ pub fn instantiate( pub fn execute( deps: DepsMut, env: Env, - _info: MessageInfo, + info: MessageInfo, msg: ExecuteMsg, ) -> StdResult { match msg { @@ -94,7 +94,53 @@ pub fn execute( pad_handle_result(pre_execution(deps, env, inputs), BLOCK_SIZE) }, ExecuteMsg::Output { outputs } => post_execution(deps, env, outputs), + ExecuteMsg::RotateGatewayKeys {} => rotate_gateway_keys(deps, env, info), + } +} + +fn rotate_gateway_keys(deps: DepsMut, env: Env, info: MessageInfo) -> StdResult { + // load config + let state = CONFIG.load(deps.storage)?; + + let caller_raw = deps.api.addr_canonicalize(info.sender.as_str())?; + + // check if the keys have already been created + if state.keyed { + //if keys were have already been created, check if admin is calling this + if state.admin != caller_raw { + return Err(StdError::generic_err( + "keys have already been created and only admin is allowed to rotate gateway keys".to_string(), + )); + } } + + // Generate secp256k1 key pair for encryption + let (secret, public) = generate_keypair(&env)?; + let encryption_keys = KeyPair { + sk: Binary(secret.serialize().to_vec()), // private key is 32 bytes, + pk: Binary(public.serialize_compressed().to_vec()), // public key is 33 bytes + }; + + // Generate secp256k1 key pair for signing messages + let (secret, public) = generate_keypair(&env)?; + let signing_keys = KeyPair { + sk: Binary(secret.serialize().to_vec()), // private key is 32 bytes, + pk: Binary(public.serialize().to_vec()), // public key is 65 bytes + }; + + CONFIG.update(deps.storage, |mut state| { + state.keyed = true; + state.encryption_keys = encryption_keys.clone(); + state.signing_keys = signing_keys.clone(); + Ok(state) + })?; + + let encryption_pubkey = encryption_keys.pk.to_base64(); + let signing_pubkey = signing_keys.pk.to_base64(); + + Ok(Response::new() + .add_attribute_plaintext("encryption_pubkey", encryption_pubkey) + .add_attribute_plaintext("signing_pubkey", signing_pubkey)) } fn create_gateway_keys(deps: DepsMut, env: Env) -> StdResult { @@ -172,6 +218,10 @@ fn pre_execution(deps: DepsMut, _env: Env, msg: PreExecutionMsg) -> StdResult StdResult StdResult StdResult StdResult StdResult { - // load task info and remove task ID from map + // load task info and remove task from map let task_info = TASK_MAP .get(deps.storage, &msg.task) - .ok_or_else(|| StdError::generic_err("task id not found"))?; + .ok_or_else(|| StdError::generic_err("task not found"))?; - // verify that input hash is correct one for Task ID + // verify that input hash is correct one for Task if msg.input_hash.as_slice() != task_info.input_hash.to_vec() { - return Err(StdError::generic_err("input hash does not match task id")); + return Err(StdError::generic_err("input hash does not match task")); } let result = match base64::decode(msg.result) { @@ -346,10 +396,10 @@ fn post_execution(deps: DepsMut, env: Env, msg: PostExecutionMsg) -> StdResult StdResult()); let callback_gas_limit = format!("0x{}", task_info.callback_gas_limit.to_be_bytes().encode_hex::()); + // task info + let result_info = ResultInfo { + source_network: env.block.chain_id, + task_destination_network: routing_info, + task_id: msg.task.task_id.to_string(), + payload_hash: payload_hash, + result: result, + packet_hash: packet_hash, + packet_signature: packet_signature, + callback_address: callback_address, + callback_selector: callback_selector, + callback_gas_limit: callback_gas_limit + }; + + RESULT_MAP.insert(deps.storage, &msg.task, &result_info)?; + Ok(Response::new() - .add_attribute_plaintext("source_network", env.block.chain_id) - .add_attribute_plaintext("task_destination_network", routing_info) - .add_attribute_plaintext("task_id", msg.task.task_id.to_string()) - .add_attribute_plaintext("payload_hash", payload_hash) - .add_attribute_plaintext("result", result) - .add_attribute_plaintext("packet_hash", packet_hash) - .add_attribute_plaintext("packet_signature", packet_signature) - .add_attribute_plaintext("callback_address", callback_address) - .add_attribute_plaintext("callback_selector", callback_selector) - .add_attribute_plaintext("callback_gas_limit", callback_gas_limit)) + .add_attribute_plaintext("source_network", result_info.source_network) + .add_attribute_plaintext("task_destination_network", result_info.task_destination_network) + .add_attribute_plaintext("task_id", result_info.task_id) + .add_attribute_plaintext("payload_hash", result_info.payload_hash) + .add_attribute_plaintext("result", result_info.result) + .add_attribute_plaintext("packet_hash", result_info.packet_hash) + .add_attribute_plaintext("packet_signature", result_info.packet_signature) + .add_attribute_plaintext("callback_address", result_info.callback_address) + .add_attribute_plaintext("callback_selector", result_info.callback_selector) + .add_attribute_plaintext("callback_gas_limit", result_info.callback_gas_limit)) } #[cfg(feature = "contract")] @@ -393,10 +459,31 @@ fn post_execution(deps: DepsMut, env: Env, msg: PostExecutionMsg) -> StdResult StdResult { let response = match msg { QueryMsg::GetPublicKeys {} => query_public_keys(deps), + QueryMsg::GetExecutionResult {task} => query_execution_result(deps, task), }; pad_query_result(response, BLOCK_SIZE) } +fn query_execution_result(deps: Deps, task: Task) -> StdResult { + + let task_info = RESULT_MAP + .get(deps.storage, &task) + .ok_or_else(|| StdError::generic_err("task not found"))?; + + to_binary(&ResultInfo { + source_network: task_info.source_network, + task_destination_network: task_info.task_destination_network, + task_id: task_info.task_id, + payload_hash: task_info.payload_hash, + result: task_info.result, + packet_hash: task_info.packet_hash, + packet_signature: task_info.packet_signature, + callback_address: task_info.callback_address, + callback_selector: task_info.callback_selector, + callback_gas_limit: task_info.callback_gas_limit + }) +} + // the encryption key will be a base64 string, the verifying key will be a '0x' prefixed hex string fn query_public_keys(deps: Deps) -> StdResult { let state: State = CONFIG.load(deps.storage)?; diff --git a/TNLS-Gateways/secret/src/msg.rs b/TNLS-Gateways/secret/src/msg.rs index dadc039..34c42ab 100644 --- a/TNLS-Gateways/secret/src/msg.rs +++ b/TNLS-Gateways/secret/src/msg.rs @@ -13,7 +13,7 @@ use crate::state::Task; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { - /// Optional admin address, env.message.sender if missing. + /// Optional admin address, info.sender if missing. pub admin: Option } @@ -24,6 +24,8 @@ pub enum ExecuteMsg { Input { inputs: PreExecutionMsg }, /// Receive results from private contract and broadcast logs for Relayer. Output { outputs: PostExecutionMsg }, + /// Rotates the gateway keys, only callable by admin. + RotateGatewayKeys {}, } #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] @@ -44,6 +46,7 @@ pub struct InputResponse { pub enum QueryMsg { /// Query the gateway's public keys. GetPublicKeys {}, + GetExecutionResult {task: Task} } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -81,6 +84,8 @@ pub struct PreExecutionMsg { pub handle: String, /// Unique random bytes used to encrypt payload. pub nonce: Binary, + /// Callback gas limit for the post execution message. + pub callback_gas_limit: u32, } impl PreExecutionMsg { diff --git a/TNLS-Gateways/secret/src/state.rs b/TNLS-Gateways/secret/src/state.rs index af0171b..0b9d9fd 100644 --- a/TNLS-Gateways/secret/src/state.rs +++ b/TNLS-Gateways/secret/src/state.rs @@ -12,6 +12,8 @@ pub static MY_ADDRESS: Item = Item::new(b"myaddr"); pub static CREATOR: Item = Item::new(b"creator"); /// Storage key for task IDs. pub static TASK_MAP: Keymap = Keymap::new(b"tasks"); +/// Storage key for task IDs. +pub static RESULT_MAP: Keymap = Keymap::new(b"results"); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { @@ -56,6 +58,30 @@ pub struct TaskInfo { /// Callback gas limit for the post execution message. pub callback_gas_limit: u32, } + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResultInfo { + /// The source network + pub source_network: String, + /// The task destination network + pub task_destination_network: String, + /// The task_id of the Result + pub task_id: String, + /// A unique hash for the task. + pub payload_hash: String, + /// The computation result + pub result: String, + /// The packet hash of the computed task + pub packet_hash: String, + /// Packet signature for the computed task + pub packet_signature: String, + /// Callback address for the post execution message. + pub callback_address: String, + /// Callback selector for the post execution message. + pub callback_selector: String, + /// Callback gas limit for the post execution message. + pub callback_gas_limit: String, +} /// A key pair using the [Binary] type #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, Default)] pub struct KeyPair { diff --git a/TNLS-Relayers/base_interface.py b/TNLS-Relayers/base_interface.py index e660a58..f111ddf 100644 --- a/TNLS-Relayers/base_interface.py +++ b/TNLS-Relayers/base_interface.py @@ -2,7 +2,7 @@ import base64 import json from typing import List -eth_chains = ['11155111', '137','42161'] +eth_chains = ['11155111'] scrt_chains = ['secret-4', 'pulsar-3'] #scrt_chains = ['secret-4'] diff --git a/TNLS-Relayers/eth_interface.py b/TNLS-Relayers/eth_interface.py index ca96a4a..76d592a 100644 --- a/TNLS-Relayers/eth_interface.py +++ b/TNLS-Relayers/eth_interface.py @@ -46,10 +46,14 @@ def create_transaction(self, contract_function, *args, **kwargs): See base_interface.py for documentation """ # create task + #structure is from eth_task_keys_to_msg + #callback_gas_limit is on the 5th position on eth_task_keys_to_msgs + print(args[2][4]) if kwargs is {}: + callback_gas_limit = int(args[2][4], 16) tx = contract_function(*args).build_transaction({ 'from': self.address, - 'gas': 2000000, + 'gas': callback_gas_limit, 'nonce': deepcopy(self.nonce) #'maxFeePerGas': self.provider.eth.max_base #'maxPriorityFeePerGas': self.provider.eth.max_priority_fee, @@ -63,9 +67,10 @@ def create_transaction(self, contract_function, *args, **kwargs): #'maxPriorityFeePerGas': self.provider.eth.max_priority_fee, }) else: + callback_gas_limit = int(args[2][4], 16) tx = contract_function(*args, **kwargs).build_transaction({ 'from': self.address, - 'gas': 2000000, + 'gas': callback_gas_limit, 'nonce': deepcopy(self.nonce) #'maxFeePerGas': self.provider.eth.max_priority_fee #'maxPriorityFeePerGas': self.provider.eth.max_priority_fee, diff --git a/TNLS-Relayers/relayer.py b/TNLS-Relayers/relayer.py index b74ec1e..687d842 100644 --- a/TNLS-Relayers/relayer.py +++ b/TNLS-Relayers/relayer.py @@ -138,7 +138,7 @@ def _thread_func(): task = self.task_list.pop() self.route_transaction(task) - if len(self.task_threads) < 5 and len(self.task_list) > 0: + if len(self.task_threads) < 10 and len(self.task_list) > 0: thread = Thread(target=_thread_func) thread.start() self.task_threads.append(thread) @@ -160,7 +160,7 @@ def run(self): self.logger.info('Polled for transactions, now have {} remaining'.format(len(self.task_list))) self.task_list_handle() self.loops_run += 1 - sleep(0.1) + sleep(0.5) pass def __str__(self): diff --git a/TNLS-Relayers/scrt_interface.py b/TNLS-Relayers/scrt_interface.py index 0cce1c2..a72aaa4 100644 --- a/TNLS-Relayers/scrt_interface.py +++ b/TNLS-Relayers/scrt_interface.py @@ -54,7 +54,6 @@ def sign_and_send_transaction(self, tx): max_retries = 10 for attempt in range(max_retries): try: - # Assuming broadcast_adapter is an async function final_tx = self.provider.tx.broadcast_adapter(tx, mode=BroadcastMode.BROADCAST_MODE_BLOCK) return final_tx except LCDResponseError as e: diff --git a/TNLS-Relayers/secret_abi.json b/TNLS-Relayers/secret_abi.json index 9b1831c..5ed9bd6 100644 --- a/TNLS-Relayers/secret_abi.json +++ b/TNLS-Relayers/secret_abi.json @@ -12,7 +12,8 @@ "user_address", "user_key", "user_pubkey", - "routing_code_hash" + "routing_code_hash", + "callback_gas_limit" ] } } diff --git a/config.yml b/config.yml index bd7dda5..4ca05b0 100644 --- a/config.yml +++ b/config.yml @@ -10,8 +10,8 @@ type: evm chain_id: "11155111" api_endpoint: https://sepolia.gateway.tenderly.co - contract_address: "0xBFE44aF8e40B6468946e9AA88fe2c6c9D0352F62" - contract_schema: '[{"inputs":[],"name":"CallbackError","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidPacketSignature","type":"error"},{"inputs":[],"name":"InvalidPayloadHash","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"InvalidSignatureSValue","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"TaskAlreadyCompleted","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"taskId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"result","type":"bytes"}],"name":"ComputedResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"task_id","type":"uint256"},{"indexed":false,"internalType":"string","name":"source_network","type":"string"},{"indexed":false,"internalType":"address","name":"user_address","type":"address"},{"indexed":false,"internalType":"string","name":"routing_info","type":"string"},{"indexed":false,"internalType":"bytes32","name":"payload_hash","type":"bytes32"},{"components":[{"internalType":"bytes","name":"user_key","type":"bytes"},{"internalType":"bytes","name":"user_pubkey","type":"bytes"},{"internalType":"string","name":"routing_code_hash","type":"string"},{"internalType":"string","name":"task_destination_network","type":"string"},{"internalType":"string","name":"handle","type":"string"},{"internalType":"bytes12","name":"nonce","type":"bytes12"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes","name":"payload_signature","type":"bytes"}],"indexed":false,"internalType":"struct Gateway.ExecutionInfo","name":"info","type":"tuple"}],"name":"logNewTask","type":"event"},{"inputs":[{"internalType":"uint256","name":"_taskId","type":"uint256"},{"internalType":"bytes","name":"_result","type":"bytes"}],"name":"callback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTaskId","type":"uint256"}],"name":"increaseTaskId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taskId","type":"uint256"},{"internalType":"string","name":"_sourceNetwork","type":"string"},{"components":[{"internalType":"bytes32","name":"payload_hash","type":"bytes32"},{"internalType":"bytes32","name":"packet_hash","type":"bytes32"},{"internalType":"bytes20","name":"callback_address","type":"bytes20"},{"internalType":"bytes4","name":"callback_selector","type":"bytes4"},{"internalType":"bytes4","name":"callback_gas_limit","type":"bytes4"},{"internalType":"bytes","name":"packet_signature","type":"bytes"},{"internalType":"bytes","name":"result","type":"bytes"}],"internalType":"struct Gateway.PostExecutionInfo","name":"_info","type":"tuple"}],"name":"postExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_numWords","type":"uint32"},{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"requestRandomness","outputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_payloadHash","type":"bytes32"},{"internalType":"address","name":"_userAddress","type":"address"},{"internalType":"string","name":"_routingInfo","type":"string"},{"components":[{"internalType":"bytes","name":"user_key","type":"bytes"},{"internalType":"bytes","name":"user_pubkey","type":"bytes"},{"internalType":"string","name":"routing_code_hash","type":"string"},{"internalType":"string","name":"task_destination_network","type":"string"},{"internalType":"string","name":"handle","type":"string"},{"internalType":"bytes12","name":"nonce","type":"bytes12"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes","name":"payload_signature","type":"bytes"}],"internalType":"struct Gateway.ExecutionInfo","name":"_info","type":"tuple"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"taskId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tasks","outputs":[{"internalType":"bytes31","name":"payload_hash_reduced","type":"bytes31"},{"internalType":"bool","name":"completed","type":"bool"}],"stateMutability":"view","type":"function"}]' + contract_address: "0x286B1e6B58a913E457509f0C30Ad4393C78f4F84" + contract_schema: '[{"type":"function","name":"callback","inputs":[{"name":"_taskId","type":"uint256","internalType":"uint256"},{"name":"_result","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"estimateRequestPrice","inputs":[{"name":"_callbackGasLimit","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"increaseTaskId","inputs":[{"name":"_newTaskId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initialize","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"payoutBalance","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"postExecution","inputs":[{"name":"_taskId","type":"uint256","internalType":"uint256"},{"name":"_sourceNetwork","type":"string","internalType":"string"},{"name":"_info","type":"tuple","internalType":"struct Gateway.PostExecutionInfo","components":[{"name":"payload_hash","type":"bytes32","internalType":"bytes32"},{"name":"packet_hash","type":"bytes32","internalType":"bytes32"},{"name":"callback_address","type":"bytes20","internalType":"bytes20"},{"name":"callback_selector","type":"bytes4","internalType":"bytes4"},{"name":"callback_gas_limit","type":"bytes4","internalType":"bytes4"},{"name":"packet_signature","type":"bytes","internalType":"bytes"},{"name":"result","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestRandomness","inputs":[{"name":"_numWords","type":"uint32","internalType":"uint32"},{"name":"_callbackGasLimit","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"send","inputs":[{"name":"_payloadHash","type":"bytes32","internalType":"bytes32"},{"name":"_userAddress","type":"address","internalType":"address"},{"name":"_callbackGasLimit","type":"uint32","internalType":"uint32"},{"name":"_routingInfo","type":"string","internalType":"string"},{"name":"_info","type":"tuple","internalType":"struct Gateway.ExecutionInfo","components":[{"name":"user_key","type":"bytes","internalType":"bytes"},{"name":"user_pubkey","type":"bytes","internalType":"bytes"},{"name":"routing_code_hash","type":"string","internalType":"string"},{"name":"task_destination_network","type":"string","internalType":"string"},{"name":"handle","type":"string","internalType":"string"},{"name":"nonce","type":"bytes12","internalType":"bytes12"},{"name":"callback_gas_limit","type":"uint32","internalType":"uint32"},{"name":"payload","type":"bytes","internalType":"bytes"},{"name":"payload_signature","type":"bytes","internalType":"bytes"}]}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"taskId","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"tasks","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"payload_hash_reduced","type":"bytes31","internalType":"bytes31"},{"name":"completed","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"upgradeHandler","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"ComputedResult","inputs":[{"name":"taskId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"result","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"contractUpgraded","inputs":[],"anonymous":false},{"type":"event","name":"logNewTask","inputs":[{"name":"task_id","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"source_network","type":"string","indexed":false,"internalType":"string"},{"name":"user_address","type":"address","indexed":false,"internalType":"address"},{"name":"routing_info","type":"string","indexed":false,"internalType":"string"},{"name":"payload_hash","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"info","type":"tuple","indexed":false,"internalType":"struct Gateway.ExecutionInfo","components":[{"name":"user_key","type":"bytes","internalType":"bytes"},{"name":"user_pubkey","type":"bytes","internalType":"bytes"},{"name":"routing_code_hash","type":"string","internalType":"string"},{"name":"task_destination_network","type":"string","internalType":"string"},{"name":"handle","type":"string","internalType":"string"},{"name":"nonce","type":"bytes12","internalType":"bytes12"},{"name":"callback_gas_limit","type":"uint32","internalType":"uint32"},{"name":"payload","type":"bytes","internalType":"bytes"},{"name":"payload_signature","type":"bytes","internalType":"bytes"}]}],"anonymous":false},{"type":"error","name":"CallbackError","inputs":[]},{"type":"error","name":"InvalidBytesLength","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidPacketSignature","inputs":[]},{"type":"error","name":"InvalidPayloadHash","inputs":[]},{"type":"error","name":"InvalidSignature","inputs":[]},{"type":"error","name":"InvalidSignatureLength","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"PaidRequestPriceTooLow","inputs":[]},{"type":"error","name":"TaskAlreadyCompleted","inputs":[]},{"type":"error","name":"TooManyVRFRandomWordsRequested","inputs":[]}]' wallet_address: "0xbb6B8abe049466f637b3Ac648E7Dd9850E193346" # "1": @@ -44,8 +44,8 @@ type: "secret" chain_id: "secret-4" api_endpoint: "https://lcd.mainnet.secretsaturn.net" - contract_address: "secret12swxjrpehrg4avsvm7nc0jcs24hk7uss2r0gr2" - code_hash: "bd6253cde923dc577e7c421d26fc74bd78aad4212bc6bdab4751e2764d678627" + contract_address: "secret16segmxqh3uw5y83vn33w550z4rqpdrk504qyzq" + code_hash: "eb42cef8a881db425789587649c5f34488af1137486f278c1a850a0784fe1cb5" wallet_address: "secret1ppry6a0puedwt5mkzdqk9h5smq98vcx0qweswf" contract_encryption_key: "Auc0vPrbwbMwx2IjFyES5kOiUXRrCqhXvcFmPlaPw7TK" contract_eth_address: "0x79061a6AfeADaE3D735f26D606fF32C47Ee0A5C2"