-
Notifications
You must be signed in to change notification settings - Fork 10
feat: track locked tokens #481
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
base: main
Are you sure you want to change the base?
Conversation
kiseln
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about transfers to other chain? We need to subtract tokens for source and add for destination
It's safer to decrease locked tokens in first callback and increase back if refund is needed
Added in 057401e |
| utxo_chain_connectors: old_state.utxo_chain_connectors, | ||
| migrated_tokens: LookupMap::new(StorageKey::MigratedTokens), | ||
| migrated_tokens: old_state.migrated_tokens, | ||
| locked_tokens: LookupMap::new(StorageKey::LockedTokens), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to pause a contract, apply migration first and unpause it later. It might be better to allow providing a vec of locked tokens for migrate methods. Which option is better?
P.S: technically if locked_tokens field is empty, then it can be considered as a paused contract already, since init_transfer, fin_transfer methods won't work until locked_tokens are populated properly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements per-chain locked-token accounting on the NEAR bridge to track NEP-141 tokens locked for each destination chain. The bridge now maintains a locked_tokens map indexed by (chain, token), incrementing balances when transferring from NEAR to other chains and enforcing availability before releasing tokens back to NEAR recipients.
Changes:
- Added
locked_tokensfield to track token balances per chain - Implemented increase/decrease operations with overflow and insufficient balance checks
- Updated transfer flows to maintain locked token accounting
- Added administrative
set_locked_tokensfunction for manual backfilling
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| near/omni-bridge/src/lib.rs | Core implementation of locked tokens tracking with get/set/increase/decrease operations integrated into transfer flows |
| near/omni-bridge/src/migrate.rs | Migration logic that initializes locked_tokens as empty map requiring manual backfilling |
| near/omni-bridge/src/tests/lib_test.rs | Unit tests for locked token tracking including insufficient balance and refund scenarios |
| near/omni-tests/src/init_transfer.rs | Updated migration test to verify locked_tokens functionality |
| near/omni-tests/src/environment.rs | Test environment setup with locked token seeding for new deployments |
| near/Cargo.toml | Version bump to 0.4.4 |
| near/Cargo.lock | Dependency updates (various minor version bumps) |
Comments suppressed due to low confidence (1)
near/omni-tests/src/init_transfer.rs:716
- The migration test now only verifies that locked_tokens can be queried after migration, but it no longer verifies that existing pending_transfers are preserved during the migration. The previous test performed an init_transfer before migration and then verified the transfer message was still accessible afterwards. Consider adding a verification that existing state (pending_transfers, finalized_transfers, etc.) is properly preserved through the migration to ensure no data loss occurs.
#[rstest]
#[tokio::test]
async fn test_migrate(build_artifacts: &BuildArtifacts) -> anyhow::Result<()> {
let sender_balance_token = 1_000_000;
let env = TestEnv::new(sender_balance_token, true, build_artifacts).await?;
let res = env
.locker_contract
.as_account()
.deploy(&build_artifacts.locker)
.await
.unwrap();
assert!(res.is_success(), "Failed to upgrade locker");
let res = env
.locker_contract
.call("migrate")
.max_gas()
.transact()
.await?;
assert!(res.is_success(), "Migration didn't succeed");
let transfer = env
.locker_contract
.call("get_locked_tokens")
.args_json(json!({
"chain_kind": ChainKind::Near,
"token_id": env.token_contract.id(),
}))
.max_gas()
.transact()
.await?;
assert_eq!(
transfer.into_result()?.json::<U128>()?,
U128(0),
"Locked tokens not migrated correctly"
);
Ok(())
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 8 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d77f951 to
05743c0
Compare
* refactor: moved lock/unlock into a separate module Also, implemented a method to get token's origin chain and added lock/unlock methods for tokens other than nep141 * feat: lock and unlock tokens coming from other chains * fix: called an incorrect helper method * feat: added tests * feat: use `deployed_tokens_v2` in all places where regular `deployed_tokens` field is used * feat: covered fast transfers with tests * chore: allow running CI on any PRs * fix: double lock for transfer to other chains * fix: clippy * fix: tests * feat: lock tokens for utxo->near as well * fix: clippy * chore: fmt * fix: removed separator at the end of token prefix * fix: unlock tokens for fast fin transfer to other chain * fix: lock/unlock for utxo transfers * feat: allow setting multiple locked tokens in one call * fix: tests * fix: don't add utxo tokens to `deployed_tokens_v2` * fix: tests * refactor: reduced code duplication in locking/unlocking logic * fix: lock net amount during fast transfer to other chain * refactor: unified lock nep141 and other tokens in one method * refactor: unified unlock nep141 and other tokens in one method * refactor: moved check if token is deployed into a separate method * fix(omni-bridge): tests * fix: treat utxo token on near as native nep141 * chore: use `is_deployed_token` method when possible * fix: don't lock tokens during utxo->near transfer * fix: clippy * chore: removed unreachable statement in `get_token_origin_chain` * fix: don't lock/unlock nep141 if chain is utxo
* refactor: moved lock/unlock into a separate module Also, implemented a method to get token's origin chain and added lock/unlock methods for tokens other than nep141 * feat: lock and unlock tokens coming from other chains * fix: called an incorrect helper method * feat: added tests * feat: use `deployed_tokens_v2` in all places where regular `deployed_tokens` field is used * feat: covered fast transfers with tests * chore: allow running CI on any PRs * fix: double lock for transfer to other chains * fix: clippy * fix: tests * feat: lock tokens for utxo->near as well * fix: clippy * chore: fmt * fix: removed separator at the end of token prefix * fix: unlock tokens for fast fin transfer to other chain * fix: lock/unlock for utxo transfers * feat: allow setting multiple locked tokens in one call * fix: tests * fix: don't add utxo tokens to `deployed_tokens_v2` * feat: enable locked tokens tracker only for selected chains * fix: tests * Update near/omni-tests/src/utxo_fin_transfer.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: tests * refactor: reduced code duplication in locking/unlocking logic * fix: lock net amount during fast transfer to other chain * refactor: unified lock nep141 and other tokens in one method * refactor: unified unlock nep141 and other tokens in one method * refactor: moved check if token is deployed into a separate method * fix(omni-bridge): tests * fix: treat utxo token on near as native nep141 * chore: use `is_deployed_token` method when possible * fix: bring back chain check * fix: mess after merge * chore(omni-tests): disable near chain for token tracking * feat: bring back chain check * feat: remove chain isolation * feat: enable token lock track for newly deployed tokens * chore: changed lock/unlock methods visibility Prevents an issue if someone accidentaly adds `#[near]` on top of the implementation section * feat: added `TokenLockController` role * feat: do not remove 0 locked from map * fix(omni-bridge): tests * chore: replaced all errors left with proper enum variants * chore: removed `Copy` trait for errors * chore: removed `enable_token` logic from tests * fix(omni-tests): json serialization * fix(omni-tests): fix fast transfer related tests * fix(omni-tests): fix fin transfer related tests * chore(omni-tests): removed unused block of code * fix: don't add an entry in locked_tokens on deploy token event * feat: added small safe guard --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Note
Deploying this requires backfilling initial locked token amounts—reindex prior bridge events to populate locked_tokens before allowing withdrawals.
This pull request introduces significant enhancements to the omni-bridge contract, primarily focused on improved token deployment tracking, token locking mechanisms, and code maintainability. The main changes include the addition of a new
deployed_tokens_v2mapping for more robust token origin tracking, the introduction of token locking logic, and various refactorings to support these features and improve code clarity.Token Deployment and Origin Tracking Enhancements:
deployed_tokens_v2(LookupMap<AccountId, ChainKind>) to theContractstruct, which enables more accurate tracking of deployed tokens and their origin chains. The contract now uses anis_deployed_tokenmethod to check token deployment status, covering both old and new mappings. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R220),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R282),[[3]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1285-R1288),[[4]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1343-R1372))get_token_origin_chainmethod to determine a token's origin chain, leveraging the new mapping, UTXO chain checks, and string pattern matching for legacy tokens. The mapping is updated as needed for non-UTXO chains. ([near/omni-bridge/src/lib.rsR1343-R1372](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1343-R1372))deployed_tokens_v2and the newis_deployed_tokenmethod, including token deployment, migration, and removal flows. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1128),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1463-R1464),[[3]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1435-R1490),[[4]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1521-R1523),[[5]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1539-R1598),[[6]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1620-R1679))Token Locking Mechanism:
locked_tokensmapping and integrated new token locking logic. Tokens are now locked as needed during fast and UTXO transfers, and lock actions are managed and reverted as appropriate in callbacks. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R232),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L865-R891),[[3]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1573-R1589),[[4]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1663-R1728))token_lockmodule andLockActionusage to support the locking mechanism. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R39-R45),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R1573-R1589))Refactoring and Consistency Improvements:
amount_without_fee()in place of manual fee subtraction throughout transfer logic, improving clarity and reducing errors. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L439-R448),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L819-R838))get_destination_chain()method. ([[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L484-R496),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L865-R891))[[1]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L842-R853),[[2]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6R961),[[3]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1025-R1047),[[4]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1044-R1064),[[5]](https://github.com/Near-One/omni-bridge/pull/481/files#diff-b60c5b1d9739aba26a808fe5bb90473c2c30a608886757604357c66a764256b6L1055-R1075))Other:
nearworkspace version to0.4.4. ([near/Cargo.tomlL4-R4](https://github.com/Near-One/omni-bridge/pull/481/files#diff-6d770b88fda0eded3e60bfa1c6d3ec511baea883965f9457f7b4dbff97a816e1L4-R4))[.github/workflows/rust.yamlL10](https://github.com/Near-One/omni-bridge/pull/481/files#diff-9ed853ee5016b3f7cb01ee3da6506fd9e926a923324f327507c34e64f83dfe10L10))These changes collectively enhance the omni-bridge's ability to accurately track tokens across chains, securely lock tokens during cross-chain operations, and maintain a cleaner, more maintainable codebase.