diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 749ba88e02..aae4afd0a7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,7 +27,7 @@ jobs: toolchain: ${{ matrix.rust }} - name: Add wasm toolchain run: | - rustup target add wasm32-unknown-unknown + rustup target add --toolchain ${{ matrix.rust }} wasm32-unknown-unknown - name: Install Clippy if: matrix.make.name == 'Clippy' diff --git a/contracts/ibc-reflect-send/src/contract.rs b/contracts/ibc-reflect-send/src/contract.rs index 3784fc57cd..be5fdd10c3 100644 --- a/contracts/ibc-reflect-send/src/contract.rs +++ b/contracts/ibc-reflect-send/src/contract.rs @@ -157,6 +157,7 @@ pub fn handle_send_funds( to_address: remote_addr, amount, timeout: env.block.time.plus_seconds(PACKET_LIFETIME).into(), + memo: "", }; let res = Response::new() diff --git a/contracts/ibc-reflect-send/src/ibc.rs b/contracts/ibc-reflect-send/src/ibc.rs index dca8cbf78c..1982f20987 100644 --- a/contracts/ibc-reflect-send/src/ibc.rs +++ b/contracts/ibc-reflect-send/src/ibc.rs @@ -414,6 +414,7 @@ mod tests { to_address, amount, timeout, + memo, }) => { assert_eq!(transfer_channel_id, channel_id.as_str()); assert_eq!(remote_addr, to_address.as_str()); diff --git a/contracts/ibc-reflect-send/tests/integration.rs b/contracts/ibc-reflect-send/tests/integration.rs index c0c2977b83..261909eae7 100644 --- a/contracts/ibc-reflect-send/tests/integration.rs +++ b/contracts/ibc-reflect-send/tests/integration.rs @@ -234,6 +234,7 @@ fn send_remote_funds() { to_address, amount, timeout, + memo, }) => { assert_eq!(transfer_channel_id, channel_id.as_str()); assert_eq!(remote_addr, to_address.as_str()); diff --git a/packages/std/src/ibc.rs b/packages/std/src/ibc.rs index 5829609e45..ce123d27a8 100644 --- a/packages/std/src/ibc.rs +++ b/packages/std/src/ibc.rs @@ -36,6 +36,11 @@ pub enum IbcMsg { amount: Coin, /// when packet times out, measured on remote chain timeout: IbcTimeout, + /// optional memo + /// can put here `{"ibc_callback":"secret1contractAddr"}` to get a callback on ack/timeout + /// see this for more info: + /// https://github.com/scrtlabs/SecretNetwork/blob/78a5f82a4/x/ibc-hooks/README.md?plain=1#L144-L188 + memo: String, }, /// Sends an IBC packet with given data over the existing channel. /// Data should be encoded in a format defined by the channel version, @@ -783,9 +788,10 @@ mod tests { to_address: "my-special-addr".into(), amount: Coin::new(12345678, "uatom"), timeout: IbcTimeout::with_timestamp(Timestamp::from_nanos(1234567890)), + memo: "", }; let encoded = to_string(&msg).unwrap(); - let expected = r#"{"transfer":{"channel_id":"channel-123","to_address":"my-special-addr","amount":{"denom":"uatom","amount":"12345678"},"timeout":{"block":null,"timestamp":"1234567890"}}}"#; + let expected = r#"{"transfer":{"channel_id":"channel-123","to_address":"my-special-addr","amount":{"denom":"uatom","amount":"12345678"},"timeout":{"block":null,"timestamp":"1234567890"},"memo":""}}"#; assert_eq!(encoded.as_str(), expected); } diff --git a/packages/std/src/results/cosmos_msg.rs b/packages/std/src/results/cosmos_msg.rs index 9067b65a7e..5a238fcf99 100644 --- a/packages/std/src/results/cosmos_msg.rs +++ b/packages/std/src/results/cosmos_msg.rs @@ -156,6 +156,7 @@ pub enum WasmMsg { /// This is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.16.0-alpha1/x/wasm/internal/types/tx.proto#L47-L61). /// `sender` is automatically filled with the current contract's address. Instantiate { + admin: Option, code_id: u64, /// code_hash is the hex encoded hash of the code. This is used by Secret Network to harden against replaying the contract /// It is used to bind the request to a destination contract in a stronger way than just the contract address which can be faked @@ -168,6 +169,33 @@ pub enum WasmMsg { /// A human-readbale label for the contract, must be unique across all contracts label: String, }, + /// Migrates a given contracts to use new wasm code. Passes a MigrateMsg to allow us to + /// customize behavior. + /// + /// Only the contract admin (as defined in wasmd), if any, is able to make this call. + /// + /// This is translated to a [MsgMigrateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L86-L96). + /// `sender` is automatically filled with the current contract's address. + Migrate { + contract_addr: String, + /// code_hash is the hex encoded hash of the **new** code. This is used by Secret Network to harden against replaying the contract + /// It is used to bind the request to a destination contract in a stronger way than just the contract address which can be faked + code_hash: String, + /// the code_id of the **new** logic to place in the given contract + code_id: u64, + /// msg is the json-encoded MigrateMsg struct that will be passed to the new code + #[derivative(Debug(format_with = "binary_to_string"))] + msg: Binary, + }, + /// Sets a new admin (for migrate) on the given contract. + /// Fails if this contract is not currently admin of the target contract. + UpdateAdmin { + contract_addr: String, + admin: String, + }, + /// Clears the admin on the given contract, so no more migration possible. + /// Fails if this contract is not currently admin of the target contract. + ClearAdmin { contract_addr: String }, } #[cfg(feature = "stargate")] @@ -188,7 +216,10 @@ pub enum VoteOption { NoWithVeto, } + /// Shortcut helper as the construction of WasmMsg::Instantiate can be quite verbose in contract code. +/// +/// When using this, `admin` is always unset. If you need more flexibility, create the message directly. pub fn wasm_instantiate( code_id: u64, code_hash: impl Into, @@ -198,6 +229,7 @@ pub fn wasm_instantiate( ) -> StdResult { let payload = to_binary(msg)?; Ok(WasmMsg::Instantiate { + admin: None, code_id, code_hash: code_hash.into(), msg: payload, diff --git a/packages/std/src/testing/mock.rs b/packages/std/src/testing/mock.rs index 9931259995..595341f714 100644 --- a/packages/std/src/testing/mock.rs +++ b/packages/std/src/testing/mock.rs @@ -253,7 +253,7 @@ pub fn mock_env() -> Env { Binary::from_base64("wLsKdf/sYqvSMI0G0aWRjob25mrIB0VQVjTjDXnDafk=").unwrap(), ), }, - transaction: Some(TransactionInfo { index: 3 }), + transaction: Some(TransactionInfo { index: 3, hash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string() }), contract: ContractInfo { address: Addr::unchecked(MOCK_CONTRACT_ADDR), code_hash: "".to_string(), diff --git a/packages/std/src/types.rs b/packages/std/src/types.rs index 5d3b91633c..55e992ec5b 100644 --- a/packages/std/src/types.rs +++ b/packages/std/src/types.rs @@ -27,6 +27,11 @@ pub struct TransactionInfo { /// using the pair (`env.block.height`, `env.transaction.index`). /// pub index: u32, + #[serde(default)] + /// The hash of the current transaction bytes. + /// aka txhash or transaction_id + /// hash = sha256(tx_bytes) + pub hash: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -50,7 +55,7 @@ pub struct BlockInfo { /// # time: Timestamp::from_nanos(1_571_797_419_879_305_533), /// # chain_id: "cosmos-testnet-14002".to_string(), /// # }, - /// # transaction: Some(TransactionInfo { index: 3 }), + /// # transaction: Some(TransactionInfo { index: 3, hash: "".to_string() }), /// # contract: ContractInfo { /// # address: Addr::unchecked("contract"), /// # code_hash: "".to_string() @@ -75,7 +80,7 @@ pub struct BlockInfo { /// # time: Timestamp::from_nanos(1_571_797_419_879_305_533), /// # chain_id: "cosmos-testnet-14002".to_string(), /// # }, - /// # transaction: Some(TransactionInfo { index: 3 }), + /// # transaction: Some(TransactionInfo { index: 3, hash: "".to_string() }), /// # contract: ContractInfo { /// # address: Addr::unchecked("contract"), /// # code_hash: "".to_string() diff --git a/rust-toolchain b/rust-toolchain index 07ade694b1..870bbe4e50 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly \ No newline at end of file +stable \ No newline at end of file