Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreign Assets Migration #3020

Merged
merged 35 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d6bcca7
add a call to freeze asset and create smart contract
ahmadkaouk Oct 21, 2024
161b4bd
add a storage value to track foreign asset migration status
ahmadkaouk Oct 22, 2024
8e5ebe5
add a call to migrate balances
ahmadkaouk Oct 23, 2024
7a20496
migrate approvals
ahmadkaouk Nov 6, 2024
3f152f7
update migration calls
ahmadkaouk Nov 11, 2024
eaf41f6
add test for start_foreign_asset_migration call
ahmadkaouk Nov 14, 2024
80eee6a
add test for balances migrations
ahmadkaouk Nov 17, 2024
7ff1cf2
add tests for approvals migration
ahmadkaouk Nov 17, 2024
4a3589f
add test for finish migration
ahmadkaouk Nov 18, 2024
0663797
add typescript tests
ahmadkaouk Nov 22, 2024
674ff42
Merge branch 'master' into ahmad-foreign-assets-migration
ahmadkaouk Nov 22, 2024
6218511
update polkadot-sdk pin
ahmadkaouk Nov 22, 2024
1c795d8
add benchmarking scenarios
ahmadkaouk Nov 24, 2024
ca7fc5f
update typescript tests
ahmadkaouk Nov 25, 2024
26e2c8b
update benchmark scenarios
ahmadkaouk Nov 25, 2024
86c46e1
fix revet when minting and approving
ahmadkaouk Nov 28, 2024
f21b22c
add local genretad weights
ahmadkaouk Nov 29, 2024
54b67db
fix format
ahmadkaouk Nov 29, 2024
59bb6d4
format
ahmadkaouk Nov 29, 2024
328b3d0
fix test build
ahmadkaouk Nov 29, 2024
537ba73
fix format
ahmadkaouk Nov 29, 2024
029dc8e
Merge branch 'master' into ahmad-foreign-assets-migration
ahmadkaouk Nov 29, 2024
478e2fc
fix test
ahmadkaouk Nov 29, 2024
ea64612
address comments and add more tests
ahmadkaouk Dec 3, 2024
181a7c2
Update pallets/moonbeam-lazy-migrations/src/lib.rs
ahmadkaouk Dec 3, 2024
63dc1bc
Apply suggestions from code review
ahmadkaouk Dec 3, 2024
7b8a5f6
allow multiple assets to be migrated
ahmadkaouk Dec 3, 2024
758efe9
update call to approve migration of assets
ahmadkaouk Dec 4, 2024
e9493ce
update benchmarks
ahmadkaouk Dec 4, 2024
9933293
fix rust tests
ahmadkaouk Dec 4, 2024
82e8a7f
fix typescript tests
ahmadkaouk Dec 4, 2024
9b12c5d
update origin
ahmadkaouk Dec 4, 2024
e7195b5
fix ci
ahmadkaouk Dec 4, 2024
445d85d
fix benchmarks
ahmadkaouk Dec 4, 2024
ebcbe01
Merge branch 'master' into ahmad-foreign-assets-migration
ahmadkaouk Dec 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
565 changes: 286 additions & 279 deletions Cargo.lock

Large diffs are not rendered by default.

50 changes: 48 additions & 2 deletions pallets/moonbeam-foreign-assets/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ use xcm::latest::Error as XcmError;
const ERC20_CALL_MAX_CALLDATA_SIZE: usize = 4 + 32 + 32; // selector + address + uint256
const ERC20_CREATE_MAX_CALLDATA_SIZE: usize = 16 * 1024; // 16Ko

// Hardcoded gas limits (from manueal binary search)
const ERC20_CREATE_GAS_LIMIT: u64 = 3_367_000; // highest failure: 3_366_000
// Hardcoded gas limits (from manual binary search)
const ERC20_CREATE_GAS_LIMIT: u64 = 3_410_000; // highest failure: 3_406_000
pub(crate) const ERC20_BURN_FROM_GAS_LIMIT: u64 = 155_000; // highest failure: 154_000
pub(crate) const ERC20_MINT_INTO_GAS_LIMIT: u64 = 155_000; // highest failure: 154_000
const ERC20_PAUSE_GAS_LIMIT: u64 = 150_000; // highest failure: 149_500
pub(crate) const ERC20_TRANSFER_GAS_LIMIT: u64 = 155_000; // highest failure: 154_000
pub(crate) const ERC20_APPROVE_GAS_LIMIT: u64 = 154_000; // highest failure: 153_000
const ERC20_UNPAUSE_GAS_LIMIT: u64 = 150_000; // highest failure: 149_500

pub enum EvmError {
Expand Down Expand Up @@ -247,6 +248,51 @@ impl<T: crate::Config> EvmCaller<T> {
Ok(())
}

pub(crate) fn erc20_approve(
erc20_contract_address: H160,
owner: H160,
spender: H160,
amount: U256,
) -> Result<(), EvmError> {
let mut input = Vec::with_capacity(ERC20_CALL_MAX_CALLDATA_SIZE);
// Selector
input.extend_from_slice(&keccak256!("approve(address,uint256)")[..4]);
// append spender address
input.extend_from_slice(H256::from(spender).as_bytes());
// append amount to be approved
input.extend_from_slice(H256::from_uint(&amount).as_bytes());
let weight_limit: Weight =
T::GasWeightMapping::gas_to_weight(ERC20_APPROVE_GAS_LIMIT, true);

let exec_info = T::EvmRunner::call(
owner,
erc20_contract_address,
input,
U256::default(),
ERC20_APPROVE_GAS_LIMIT,
None,
None,
None,
Default::default(),
false,
false,
Some(weight_limit),
Some(0),
&<T as pallet_evm::Config>::config(),
)
.map_err(|_| EvmError::EvmCallFail)?;

ensure!(
matches!(
exec_info.exit_reason,
ExitReason::Succeed(ExitSucceed::Returned | ExitSucceed::Stopped)
),
EvmError::EvmCallFail
);

Ok(())
}

pub(crate) fn erc20_burn_from(
erc20_contract_address: H160,
who: H160,
Expand Down
69 changes: 68 additions & 1 deletion pallets/moonbeam-foreign-assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,61 @@ pub mod pallet {

/// Compute asset contract address from asset id
#[inline]
pub(crate) fn contract_address_from_asset_id(asset_id: AssetId) -> H160 {
pub fn contract_address_from_asset_id(asset_id: AssetId) -> H160 {
let mut buffer = [0u8; 20];
buffer[..4].copy_from_slice(&FOREIGN_ASSETS_PREFIX);
buffer[4..].copy_from_slice(&asset_id.to_be_bytes());
H160(buffer)
}

pub fn register_foreign_asset(
asset_id: AssetId,
xcm_location: Location,
decimals: u8,
symbol: BoundedVec<u8, ConstU32<256>>,
name: BoundedVec<u8, ConstU32<256>>,
) -> DispatchResult {
// Ensure such an assetId does not exist
ensure!(
!AssetsById::<T>::contains_key(&asset_id),
Error::<T>::AssetAlreadyExists
);

ensure!(
!AssetsByLocation::<T>::contains_key(&xcm_location),
Error::<T>::LocationAlreadyExists
);

ensure!(
AssetsById::<T>::count() < T::MaxForeignAssets::get(),
Error::<T>::TooManyForeignAssets
);

ensure!(
T::AssetIdFilter::contains(&asset_id),
Error::<T>::AssetIdFiltered
);

let symbol = core::str::from_utf8(&symbol).map_err(|_| Error::<T>::InvalidSymbol)?;
let name = core::str::from_utf8(&name).map_err(|_| Error::<T>::InvalidTokenName)?;

let contract_address = EvmCaller::<T>::erc20_create(asset_id, decimals, symbol, name)?;

// Insert the association assetId->foreigAsset
// Insert the association foreigAsset->assetId
AssetsById::<T>::insert(&asset_id, &xcm_location);
AssetsByLocation::<T>::insert(&xcm_location, (asset_id, AssetStatus::Active));

T::OnForeignAssetCreated::on_asset_created(&xcm_location, &asset_id);

Self::deposit_event(Event::ForeignAssetCreated {
contract_address,
asset_id,
xcm_location,
});
Ok(())
}

/// Mint an asset into a specific account
pub fn mint_into(
asset_id: AssetId,
Expand All @@ -259,6 +307,25 @@ pub mod pallet {
})
.map_err(Into::into)
}

/// Aprrove a spender to spend a certain amount of tokens from the owner account
pub fn approve(
asset_id: AssetId,
owner: T::AccountId,
spender: T::AccountId,
amount: U256,
) -> Result<(), evm::EvmError> {
// We perform the evm call in a storage transaction to ensure that if it fail
// any contract storage changes are rolled back.
EvmCaller::<T>::erc20_approve(
Self::contract_address_from_asset_id(asset_id),
T::AccountIdToH160::convert(owner),
T::AccountIdToH160::convert(spender),
amount,
)
.map_err(Into::into)
}

pub fn weight_of_erc20_burn() -> Weight {
T::GasWeightMapping::gas_to_weight(evm::ERC20_BURN_FROM_GAS_LIMIT, true)
}
Expand Down
12 changes: 12 additions & 0 deletions pallets/moonbeam-lazy-migrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-scheduler = { workspace = true }
pallet-assets = { workspace = true }
pallet-asset-manager = { workspace = true }
pallet-balances = { workspace = true }
pallet-moonbeam-foreign-assets = { workspace = true }
parity-scale-codec = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
xcm = { workspace = true }
xcm-primitives = { workspace = true }

environmental = { workspace = true }

# Frontier
pallet-evm = { workspace = true, features = ["forbid-evm-reentrancy"] }
Expand All @@ -34,13 +40,15 @@ frame-benchmarking = { workspace = true, optional = true }
frame-benchmarking = { workspace = true, features = ["std"] }
pallet-balances = { workspace = true, features = ["std", "insecure_zero_ed"] }
pallet-timestamp = { workspace = true, features = ["std"] }
precompile-utils = { workspace = true, features = ["std"] }
rlp = { workspace = true, features = ["std"] }
sp-io = { workspace = true, features = ["std"] }

[features]
default = ["std"]
runtime-benchmarks = ["frame-benchmarking"]
std = [
"environmental/std",
"pallet-balances/std",
"frame-support/std",
"frame-system/std",
Expand All @@ -52,7 +60,11 @@ std = [
"pallet-evm/std",
"pallet-timestamp/std",
"pallet-assets/std",
"pallet-moonbeam-foreign-assets/std",
"pallet-asset-manager/std",
"precompile-utils/std",
"cumulus-primitives-storage-weight-reclaim/std",
"rlp/std",
"xcm-primitives/std",
]
try-runtime = ["frame-support/try-runtime"]
Loading
Loading