diff --git a/CHANGES.md b/CHANGES.md index 65c3208eb..42455ab03 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [3.6.4] 2024-07-22 + +### Additions + +- Added a possibility to provide amount of gas for the `state_migration` callback in the `upgrade` + transaction by [@aleksuss]. ([#937]) + +[#937]: https://github.com/aurora-is-near/aurora-engine/pull/937 + ## [3.6.3] 2024-04-16 ### Additions @@ -651,7 +660,8 @@ struct SubmitResult { ## [1.0.0] - 2021-05-12 -[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.3...develop +[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.4...develop +[3.6.4]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.3...3.6.4 [3.6.3]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.2...3.6.3 [3.6.2]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.1...3.6.2 [3.6.1]: https://github.com/aurora-is-near/aurora-engine/compare/3.6.0...3.6.1 diff --git a/Cargo.lock b/Cargo.lock index 477c00ea9..7165d7fad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,7 +270,7 @@ dependencies = [ [[package]] name = "aurora-engine" -version = "3.6.3" +version = "3.6.4" dependencies = [ "aurora-engine-hashchain", "aurora-engine-modexp", @@ -4569,9 +4569,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring", diff --git a/VERSION b/VERSION index 4a788a01d..0f44168a4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.6.3 +3.6.4 diff --git a/engine-tests-connector/src/connector.rs b/engine-tests-connector/src/connector.rs index 00dca442c..fc7205194 100644 --- a/engine-tests-connector/src/connector.rs +++ b/engine-tests-connector/src/connector.rs @@ -222,15 +222,7 @@ async fn test_ft_transfer_call_eth() -> anyhow::Result<()> { ); let transfer_amount: U128 = 50.into(); - let fee: u128 = 30; - let mut msg = U256::from(fee).as_byte_slice().to_vec(); - msg.append( - &mut validate_eth_address(RECIPIENT_ETH_ADDRESS) - .as_bytes() - .to_vec(), - ); - - let message = [CONTRACT_ACC, hex::encode(msg).as_str()].join(":"); + let message = ft_transfer_msg(CONTRACT_ACC, 30, RECIPIENT_ETH_ADDRESS); let memo: Option = None; let res = user_acc .call(contract.engine_contract.id(), "ft_transfer_call") @@ -288,7 +280,7 @@ async fn test_ft_transfer_call_without_fee() -> anyhow::Result<()> { ); let transfer_amount: U128 = 50.into(); - let message = RECIPIENT_ETH_ADDRESS; + let message = ft_transfer_msg("relayer.root", 0, RECIPIENT_ETH_ADDRESS); let memo: Option = None; let res = user_acc .call(contract.engine_contract.id(), "ft_transfer_call") @@ -302,7 +294,7 @@ async fn test_ft_transfer_call_without_fee() -> anyhow::Result<()> { .deposit(ONE_YOCTO) .transact() .await?; - assert!(res.is_success()); + assert!(res.is_success(), "{res:#?}"); assert_eq!( contract.get_eth_on_near_balance(user_acc.id()).await?.0, @@ -592,14 +584,7 @@ async fn test_ft_transfer_call_without_relayer() -> anyhow::Result<()> { ); let transfer_amount: U128 = 50.into(); - let fee: u128 = 30; - let mut msg = U256::from(fee).as_byte_slice().to_vec(); - let recipient_address = validate_eth_address(RECIPIENT_ETH_ADDRESS); - msg.append(&mut recipient_address.as_bytes().to_vec()); - - let relayer_id = "relayer.root"; - let message = [relayer_id, hex::encode(msg).as_str()].join(":"); - + let message = ft_transfer_msg("relayer.root", 30, RECIPIENT_ETH_ADDRESS); let memo: Option = None; let res = user_acc .call(contract.engine_contract.id(), "ft_transfer_call") @@ -624,7 +609,9 @@ async fn test_ft_transfer_call_without_relayer() -> anyhow::Result<()> { transfer_amount.0 ); assert_eq!( - contract.get_eth_balance(&recipient_address).await?, + contract + .get_eth_balance(&validate_eth_address(RECIPIENT_ETH_ADDRESS)) + .await?, transfer_amount.0 ); assert_eq!(contract.total_supply().await?, DEPOSITED_AMOUNT); @@ -637,15 +624,7 @@ async fn test_ft_transfer_call_fee_greater_than_amount() -> anyhow::Result<()> { contract.call_deposit_eth_to_near().await?; let transfer_amount: U128 = 10.into(); - let fee: u128 = 12; - let mut msg = U256::from(fee).as_byte_slice().to_vec(); - msg.append( - &mut validate_eth_address(RECIPIENT_ETH_ADDRESS) - .as_bytes() - .to_vec(), - ); - let relayer_id = "relayer.root"; - let message = [relayer_id, hex::encode(msg).as_str()].join(":"); + let message = ft_transfer_msg("relayer.root", 12, RECIPIENT_ETH_ADDRESS); let memo: Option = None; let user_acc = contract .create_sub_account(DEPOSITED_RECIPIENT_NAME) @@ -1337,3 +1316,11 @@ async fn test_ft_metadata() -> anyhow::Result<()> { assert_eq!(metadata.symbol, m.symbol); Ok(()) } + +fn ft_transfer_msg(relayer_id: &str, fee: u128, recipient: &str) -> String { + let mut msg = U256::from(fee).as_byte_slice().to_vec(); + let recipient_address = validate_eth_address(recipient); + + msg.extend(recipient_address.as_bytes()); + [relayer_id, hex::encode(msg).as_str()].join(":") +} diff --git a/engine-tests-connector/src/utils.rs b/engine-tests-connector/src/utils.rs index 254e636cb..78826b383 100644 --- a/engine-tests-connector/src/utils.rs +++ b/engine-tests-connector/src/utils.rs @@ -41,7 +41,7 @@ pub struct TestContract { } impl TestContract { - pub async fn deploy_aurora_contract() -> anyhow::Result<(Contract, Contract, Account)> { + async fn deploy_aurora_contract() -> anyhow::Result<(Contract, Contract, Account)> { use near_workspaces::{ types::{KeyType, SecretKey}, AccessKey, @@ -141,6 +141,14 @@ impl TestContract { .await?; assert!(res.is_success()); + let result = eth_connector_contract + .call("pa_unpause_feature") + .args_json(json!({ "key": "ALL" })) + .max_gas() + .transact() + .await?; + assert!(result.is_success(), "{result:#?}"); + let chain_id = [0u8; 32]; let res = engine_contract .call("new") diff --git a/engine-tests/src/utils/workspace.rs b/engine-tests/src/utils/workspace.rs index 2f7fde05a..560e78bf4 100644 --- a/engine-tests/src/utils/workspace.rs +++ b/engine-tests/src/utils/workspace.rs @@ -85,6 +85,15 @@ async fn init_eth_connector(aurora: &EngineContract) -> anyhow::Result<()> { .await?; assert!(result.is_success()); + // By default, the contract is paused. So we need to unpause it. + let result = contract + .call("pa_unpause_feature") + .args_json(json!({ "key": "ALL" })) + .max_gas() + .transact() + .await?; + assert!(result.is_success()); + let result = aurora .set_eth_connector_contract_account(contract_account.id(), WithdrawSerializeType::Borsh) .transact() diff --git a/engine-types/src/parameters/engine.rs b/engine-types/src/parameters/engine.rs index f535356a1..500b5a959 100644 --- a/engine-types/src/parameters/engine.rs +++ b/engine-types/src/parameters/engine.rs @@ -339,6 +339,15 @@ pub struct RelayerKeyArgs { pub type FullAccessKeyArgs = RelayerKeyArgs; +/// Parameters for upgrading the contract. +#[derive(Debug, Clone, Eq, PartialEq, BorshSerialize, BorshDeserialize)] +pub struct UpgradeParams { + /// Code for upgrading. + pub code: Vec, + /// Amount of gas for the state migration. + pub state_migration_gas: Option, +} + mod chain_id_deserialize { use crate::types::{u256_to_arr, RawU256}; use primitive_types::U256; diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 4f5c5d854..fe57caa2a 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aurora-engine" -version = "3.6.3" +version = "3.6.4" authors.workspace = true edition.workspace = true homepage.workspace = true diff --git a/engine/src/contract_methods/admin.rs b/engine/src/contract_methods/admin.rs index 50eaf4694..ae00306e5 100644 --- a/engine/src/contract_methods/admin.rs +++ b/engine/src/contract_methods/admin.rs @@ -29,7 +29,7 @@ use aurora_engine_sdk::{ io::{StorageIntermediate, IO}, promise::PromiseHandler, }; -use aurora_engine_types::parameters::engine::FullAccessKeyArgs; +use aurora_engine_types::parameters::engine::{FullAccessKeyArgs, UpgradeParams}; use aurora_engine_types::types::{NearGas, ZERO_YOCTO}; use aurora_engine_types::{ borsh::BorshDeserialize, @@ -38,7 +38,7 @@ use aurora_engine_types::{ NewCallArgs, PausePrecompilesCallArgs, RelayerKeyArgs, RelayerKeyManagerArgs, SetOwnerArgs, SetUpgradeDelayBlocksArgs, StartHashchainArgs, }, - promise::{PromiseAction, PromiseBatchAction, PromiseCreateArgs}, + promise::{PromiseAction, PromiseBatchAction}, }, storage::{self, KeyPrefix}, types::{Address, Yocto}, @@ -48,7 +48,7 @@ use function_name::named; const CODE_KEY: &[u8; 4] = b"CODE"; const CODE_STAGE_KEY: &[u8; 10] = b"CODE_STAGE"; -const GAS_FOR_STATE_MIGRATION: NearGas = NearGas::new(100_000_000_000_000); +const GAS_FOR_STATE_MIGRATION: NearGas = NearGas::new(50_000_000_000_000); #[named] pub fn new(mut io: I, env: &E) -> Result<(), ContractError> { @@ -189,23 +189,30 @@ pub fn upgrade( require_running(&state)?; require_owner_only(&state, &env.predecessor_account_id())?; - let code = io.read_input().to_vec(); - let current_account_id = env.current_account_id(); - let batch = PromiseBatchAction { - target_account_id: current_account_id.clone(), - actions: vec![PromiseAction::DeployContract { code }], - }; - let state_migration_callback = PromiseCreateArgs { - target_account_id: current_account_id, - method: "state_migration".to_string(), - args: vec![], - attached_balance: ZERO_YOCTO, - attached_gas: GAS_FOR_STATE_MIGRATION, + let input = io.read_input().to_vec(); + let (code, state_migration_gas) = match UpgradeParams::try_from_slice(&input) { + Ok(args) => ( + args.code, + args.state_migration_gas + .map_or(GAS_FOR_STATE_MIGRATION, NearGas::new), + ), + Err(_) => (input, GAS_FOR_STATE_MIGRATION), // Backward compatibility }; - let promise_id = unsafe { - let base_id = handler.promise_create_batch(&batch); - handler.promise_attach_callback(base_id, &state_migration_callback) + + let target_account_id = env.current_account_id(); + let batch = PromiseBatchAction { + target_account_id, + actions: vec![ + PromiseAction::DeployContract { code }, + PromiseAction::FunctionCall { + name: "state_migration".to_string(), + args: vec![], + attached_yocto: ZERO_YOCTO, + gas: state_migration_gas, + }, + ], }; + let promise_id = unsafe { handler.promise_create_batch(&batch) }; handler.promise_return(promise_id);